Package: imms Version: 2.0.1-3 Followup-For: Bug #292777 -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Attached. I have only briefly tested this, so beware. This patch works by getting rid of the call to popen (and thus the shell). It replaces it with pipe, fork, exec, etc. - -- System Information: Debian Release: 3.1 APT prefers testing APT policy: (500, 'testing'), (130, 'unstable'), (120, 'experimental') Architecture: i386 (i686) Kernel: Linux 2.6.10-bohr Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Versions of packages imms depends on: ii fftw3 3.0.1-11 Library for computing Fast Fourier ii libc6 2.3.2.ds1-20 GNU C Library: Shared libraries an ii libgcc1 1:3.4.3-6 GCC support library ii libglib1.2 1.2.10-9 The GLib library of C routines ii libglib2.0-0 2.6.1-2 The GLib library of C routines ii libgtk1.2 1.2.10-17 The GIMP Toolkit set of widgets fo ii libpcre3 4.5-1.1 Perl 5 Compatible Regular Expressi ii libsqlite3-0 3.0.8-3 SQLite 3 shared library ii libstdc++5 1:3.3.5-5 The GNU Standard C++ Library v3 ii libtag1 1.3.1-1 TagLib Audio Meta-Data Library ii libx11-6 4.3.0.dfsg.1-10 X Window System protocol client li ii libxext6 4.3.0.dfsg.1-10 X Window System miscellaneous exte ii libxi6 4.3.0.dfsg.1-10 X Window System Input extension li ii xlibs 4.3.0.dfsg.1-10 X Keyboard Extension (XKB) configu ii xmms 1.2.10-2 Versatile X audio player that look ii zlib1g 1:1.2.2-3 compression library - runtime - -- no debconf information -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (GNU/Linux) iD8DBQFB+/PU+z+IwlXqWf4RAo/AAJ9j7Psf8FAh38PBhokHAX+KhWXFSwCfWLLc N850NnqlEllvVuf7KpgaNhE= =jFS1 -----END PGP SIGNATURE-----
--- analyzer.cc 2004-12-09 15:13:24.000000000 -0500 +++ analyzer.cc.new 2005-01-29 15:35:19.000000000 -0500 @@ -1,5 +1,7 @@ -#include <stdio.h> +#include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> +#include <stdio.h> #include <iostream> #include <string> #include <fstream> @@ -44,17 +46,53 @@ return -4; } - ostringstream command; - command << "nice -n 15 sox \"" << path << "\" -t .raw -w -u -c 1 -r " - << SAMPLERATE << " -"; -#ifdef DEBUG - cout << "analyzer: Executing: " << command.str() << endl; -#endif - FILE *p = popen(command.str().c_str(), "r"); + // Do a popen the long way to avoid the shell. + int p_fds[2]; + if (-1 == pipe(p_fds)) + { + cerr << "analyzer: Could not open pipe: " << strerror(errno) + << endl; + return -2; + } + + int child_pid = fork(); + if (child_pid == -1) + { + cerr << "analyzer: Could not fork: " << strerror(errno) << endl; + return -2; + } + else if (child_pid == 0) + { + ostringstream sample_rate; + sample_rate << SAMPLERATE; + + if (-1 == dup2(p_fds[1], STDOUT_FILENO)) + { + cerr << "analyzer: Could not dup2: " << strerror(errno) << endl; + return -2; + } + if (-1 == nice(15)) + { + cerr << "analyzer: could not renice: " << strerror(errno) << endl; + return -2; + } + if (-1 == execlp("sox", "sox", path.c_str(), "-t", ".raw", "-w", + "-u", "-c", "1", "-r", sample_rate.str().c_str(), + "-", (char*)NULL)) + { + cerr << "could not exec sox: " << strerror(errno) << endl; + return -2; + } + } + + // The child performed an exec above, so we only get here if we're + // the parent. + close(p_fds[1]); // otherwise, read wont fail. + FILE *p = fdopen(p_fds[0], "r"); if (!p) { - cerr << "analyzer: Could not open pipe!" << endl; + cerr << "analyzer: Could not fdopen pipe!" << endl; return -2; } @@ -77,10 +115,7 @@ SpectrumAnalyzer analyzer(path); if (analyzer.is_known()) - { - cout << "analyzer: Already analyzed - skipping." << endl; - return 1; - } + throw std::string("analyzer: Already analyzed - skipping."); while (fread(indata + OVERLAP, sizeof(sample_t), READSIZE, p) == READSIZE) @@ -106,7 +141,22 @@ } catch (std::string &s) { cerr << s << endl; } - pclose(p); + fclose(p); + kill(child_pid, SIGKILL); // make sure + int sox_status; + if (-1 == waitpid(child_pid, &sox_status, 0)) + cerr << "WARNING: waitpid failed: " << strerror(errno) << endl; + + if (WIFEXITED(sox_status) && 0 != WEXITSTATUS(sox_status)) + { + cerr << "WARNING: sox exited with unclean status " + << WEXITSTATUS(sox_status) << ".\n"; + } + else if (WIFSIGNALED(sox_status) && SIGKILL != WTERMSIG(sox_status)) + { + cerr << "WARNING: sox exited on signal " << WTERMSIG(sox_status) + << ".\n"; + } return 0; }