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