*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <string.h> /* strdup() */
#include <stdlib.h>
# include <dirent.h>
#endif
+#ifdef HAVE_FORK
+# include <sys/time.h>
+# include <unistd.h>
+# include <errno.h>
+# include <sys/wait.h>
+#endif
+
+#if defined(WIN32) || defined(UNDER_CE)
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+#ifdef UNDER_CE
+# define strcoll strcmp
+#endif
+
/*****************************************************************************
* getenv: just in case, but it should never be called
*****************************************************************************/
/*****************************************************************************
* vasprintf:
*****************************************************************************/
-#if !defined(HAVE_VASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
+#if !defined(HAVE_VASPRINTF) || defined(__APPLE__) || defined(SYS_BEOS)
int vlc_vasprintf(char **strp, const char *fmt, va_list ap)
{
/* Guess we need no more than 100 bytes. */
/*****************************************************************************
* asprintf:
*****************************************************************************/
-#if !defined(HAVE_ASPRINTF) || defined(SYS_DARWIN) || defined(SYS_BEOS)
+#if !defined(HAVE_ASPRINTF) || defined(__APPLE__) || defined(SYS_BEOS)
int vlc_asprintf( char **strp, const char *fmt, ... )
{
va_list args;
}
#endif
+/*****************************************************************************
+ * lldiv: returns quotient and remainder
+ *****************************************************************************/
+#if defined(SYS_BEOS)
+lldiv_t vlc_lldiv( long long numer, long long denom )
+{
+ lldiv_t d;
+ d.quot = numer / denom;
+ d.rem = numer % denom;
+ return d;
+}
+#endif
+
/*****************************************************************************
* vlc_*dir_wrapper: wrapper under Windows to return the list of drive letters
* when called with an empty argument or just '\'
*****************************************************************************/
-#if defined(WIN32) || defined(UNDER_CE)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h> /* for GetLogicalDrives */
-
+#if defined(WIN32) && !defined(UNDER_CE)
typedef struct vlc_DIR
{
DIR *p_real_dir;
free( p_dir );
return 0;
}
+#else
+void *vlc_opendir_wrapper( const char *psz_path )
+{
+ return (void *)opendir( psz_path );
+}
+struct dirent *vlc_readdir_wrapper( void *_p_dir )
+{
+ return readdir( (DIR *)_p_dir );
+}
+int vlc_closedir_wrapper( void *_p_dir )
+{
+ return closedir( (DIR *)_p_dir );
+}
#endif
/*****************************************************************************
}
#endif
+#if defined (WIN32) || !defined (HAVE_SHARED_LIBVLC)
/*****************************************************************************
* dgettext: gettext for plugins.
*****************************************************************************/
return (char *)msgid;
#endif
}
+#endif
/*****************************************************************************
* count_utf8_string: returns the number of characters in the string.
* wraptext: inserts \n at convenient places to wrap the text.
* Returns the modified string in a new buffer.
*****************************************************************************/
-char *vlc_wraptext( const char *psz_text, int i_line, vlc_bool_t b_utf8 )
+char *vlc_wraptext( const char *psz_text, int i_line )
{
int i_len;
char *psz_line, *psz_new_text;
psz_line = psz_new_text = strdup( psz_text );
- if( b_utf8 )
- i_len = count_utf8_string( psz_text );
- else
- i_len = strlen( psz_text );
+ i_len = count_utf8_string( psz_text );
while( i_len > i_line )
{
int i_count = 0;
while( i_count <= i_line && *psz_parser != '\n' )
{
- if( b_utf8 )
- {
- while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
- }
+ while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
psz_parser++;
i_count++;
}
/* Find the furthest space. */
while( psz_parser > psz_line && *psz_parser != ' ' )
{
- if( b_utf8 )
- {
- while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser--;
- }
+ while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser--;
psz_parser--;
i_count--;
}
/* Wrapping has failed. Find the first space or newline */
while( i_count < i_len && *psz_parser != ' ' && *psz_parser != '\n' )
{
- if( b_utf8 )
- {
- while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
- }
+ while( *((unsigned char *)psz_parser) >= 0x80UL ) psz_parser++;
psz_parser++;
i_count++;
}
#endif
}
-size_t vlc_iconv( vlc_iconv_t cd, char **inbuf, size_t *inbytesleft,
+size_t vlc_iconv( vlc_iconv_t cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft )
{
#if defined(HAVE_ICONV)
- return iconv( cd, inbuf, inbytesleft, outbuf, outbytesleft );
+ return iconv( cd, (ICONV_CONST char **)inbuf, inbytesleft,
+ outbuf, outbytesleft );
#else
- int i_bytes = __MIN(*inbytesleft, *outbytesleft);
+ int i_bytes;
+
+ if (inbytesleft == NULL || outbytesleft == NULL)
+ {
+ return 0;
+ }
+
+ i_bytes = __MIN(*inbytesleft, *outbytesleft);
if( !inbuf || !outbuf || !i_bytes ) return (size_t)(-1);
memcpy( *outbuf, *inbuf, i_bytes );
inbuf += i_bytes;
free( psz_orig );
return argv;
}
+
+/*************************************************************************
+ * vlc_execve: Execute an external program with a given environment,
+ * wait until it finishes and return its standard output
+ *************************************************************************/
+int __vlc_execve( vlc_object_t *p_object, int i_argc, char **ppsz_argv,
+ char **ppsz_env, char *psz_cwd, char *p_in, int i_in,
+ char **pp_data, int *pi_data )
+{
+#ifdef HAVE_FORK
+ int pi_stdin[2];
+ int pi_stdout[2];
+ pid_t i_child_pid;
+
+ pipe( pi_stdin );
+ pipe( pi_stdout );
+
+ if ( (i_child_pid = fork()) == -1 )
+ {
+ msg_Err( p_object, "unable to fork (%s)", strerror(errno) );
+ return -1;
+ }
+
+ if ( i_child_pid == 0 )
+ {
+ close(0);
+ dup(pi_stdin[1]);
+ close(pi_stdin[0]);
+
+ close(1);
+ dup(pi_stdout[1]);
+ close(pi_stdout[0]);
+
+ close(2);
+
+ if ( psz_cwd != NULL )
+ chdir( psz_cwd );
+ execve( ppsz_argv[0], ppsz_argv, ppsz_env );
+ exit(1);
+ }
+
+ close(pi_stdin[1]);
+ close(pi_stdout[1]);
+ if ( !i_in )
+ close( pi_stdin[0] );
+
+ *pi_data = 0;
+ *pp_data = malloc( 1025 ); /* +1 for \0 */
+
+ while ( !p_object->b_die )
+ {
+ int i_ret, i_status;
+ fd_set readfds, writefds;
+ struct timeval tv;
+
+ FD_ZERO( &readfds );
+ FD_ZERO( &writefds );
+ FD_SET( pi_stdout[0], &readfds );
+ if ( i_in )
+ FD_SET( pi_stdin[0], &writefds );
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 10000;
+
+ i_ret = select( pi_stdin[0] > pi_stdout[0] ? pi_stdin[0] + 1 :
+ pi_stdout[0] + 1, &readfds, &writefds, NULL, &tv );
+ if ( i_ret > 0 )
+ {
+ if ( FD_ISSET( pi_stdout[0], &readfds ) )
+ {
+ ssize_t i_read = read( pi_stdout[0], &(*pp_data)[*pi_data],
+ 1024 );
+ if ( i_read > 0 )
+ {
+ *pi_data += i_read;
+ *pp_data = realloc( *pp_data, *pi_data + 1025 );
+ }
+ }
+ if ( FD_ISSET( pi_stdin[0], &writefds ) )
+ {
+ ssize_t i_write = write( pi_stdin[0], p_in, __MIN(i_in, 1024) );
+
+ if ( i_write > 0 )
+ {
+ p_in += i_write;
+ i_in -= i_write;
+ }
+ if ( !i_in )
+ close( pi_stdin[0] );
+ }
+ }
+
+ if ( waitpid( i_child_pid, &i_status, WNOHANG ) == i_child_pid )
+ {
+ if ( WIFEXITED( i_status ) )
+ {
+ if ( WEXITSTATUS( i_status ) )
+ {
+ msg_Warn( p_object,
+ "child %s returned with error code %d",
+ ppsz_argv[0], WEXITSTATUS( i_status ) );
+ }
+ }
+ else
+ {
+ if ( WIFSIGNALED( i_status ) )
+ {
+ msg_Warn( p_object,
+ "child %s quit on signal %d", ppsz_argv[0],
+ WTERMSIG( i_status ) );
+ }
+ }
+ if ( i_in )
+ close( pi_stdin[0] );
+ close( pi_stdout[0] );
+ break;
+ }
+
+ if ( i_ret < 0 && errno != EINTR )
+ {
+ msg_Warn( p_object, "select failed (%s)", strerror(errno) );
+ }
+ }
+
+#elif defined( WIN32 ) && !defined( UNDER_CE )
+ SECURITY_ATTRIBUTES saAttr;
+ PROCESS_INFORMATION piProcInfo;
+ STARTUPINFO siStartInfo;
+ BOOL bFuncRetn = FALSE;
+ HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr;
+ DWORD i_status;
+ char *psz_cmd, *p_env, *p;
+ char **ppsz_parser;
+ int i_size;
+
+ /* Set the bInheritHandle flag so pipe handles are inherited. */
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ /* Create a pipe for the child process's STDOUT. */
+ if ( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0 ) )
+ {
+ msg_Err( p_object, "stdout pipe creation failed" );
+ return -1;
+ }
+
+ /* Ensure the read handle to the pipe for STDOUT is not inherited. */
+ SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, 0 );
+
+ /* Create a pipe for the child process's STDIN. */
+ if ( !CreatePipe( &hChildStdinRd, &hChildStdinWr, &saAttr, 0 ) )
+ {
+ msg_Err( p_object, "stdin pipe creation failed" );
+ return -1;
+ }
+
+ /* Ensure the write handle to the pipe for STDIN is not inherited. */
+ SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, 0 );
+
+ /* Set up members of the PROCESS_INFORMATION structure. */
+ ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
+
+ /* Set up members of the STARTUPINFO structure. */
+ ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.hStdError = hChildStdoutWr;
+ siStartInfo.hStdOutput = hChildStdoutWr;
+ siStartInfo.hStdInput = hChildStdinRd;
+ siStartInfo.wShowWindow = SW_HIDE;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+
+ /* Set up the command line. */
+ psz_cmd = malloc(32768);
+ psz_cmd[0] = '\0';
+ i_size = 32768;
+ ppsz_parser = &ppsz_argv[0];
+ while ( ppsz_parser[0] != NULL && i_size > 0 )
+ {
+ /* Protect the last argument with quotes ; the other arguments
+ * are supposed to be already protected because they have been
+ * passed as a command-line option. */
+ if ( ppsz_parser[1] == NULL )
+ {
+ strncat( psz_cmd, "\"", i_size );
+ i_size--;
+ }
+ strncat( psz_cmd, *ppsz_parser, i_size );
+ i_size -= strlen( *ppsz_parser );
+ if ( ppsz_parser[1] == NULL )
+ {
+ strncat( psz_cmd, "\"", i_size );
+ i_size--;
+ }
+ strncat( psz_cmd, " ", i_size );
+ i_size--;
+ ppsz_parser++;
+ }
+
+ /* Set up the environment. */
+ p = p_env = malloc(32768);
+ i_size = 32768;
+ ppsz_parser = &ppsz_env[0];
+ while ( *ppsz_parser != NULL && i_size > 0 )
+ {
+ memcpy( p, *ppsz_parser,
+ __MIN((int)(strlen(*ppsz_parser) + 1), i_size) );
+ p += strlen(*ppsz_parser) + 1;
+ i_size -= strlen(*ppsz_parser) + 1;
+ ppsz_parser++;
+ }
+ *p = '\0';
+
+ /* Create the child process. */
+ bFuncRetn = CreateProcess( NULL,
+ psz_cmd, // command line
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ 0, // creation flags
+ p_env,
+ psz_cwd,
+ &siStartInfo, // STARTUPINFO pointer
+ &piProcInfo ); // receives PROCESS_INFORMATION
+
+ free( psz_cmd );
+ free( p_env );
+
+ if ( bFuncRetn == 0 )
+ {
+ msg_Err( p_object, "child creation failed" );
+ return -1;
+ }
+
+ /* Read from a file and write its contents to a pipe. */
+ while ( i_in > 0 && !p_object->b_die )
+ {
+ DWORD i_written;
+ if ( !WriteFile( hChildStdinWr, p_in, i_in, &i_written, NULL ) )
+ break;
+ i_in -= i_written;
+ p_in += i_written;
+ }
+
+ /* Close the pipe handle so the child process stops reading. */
+ CloseHandle(hChildStdinWr);
+
+ /* Close the write end of the pipe before reading from the
+ * read end of the pipe. */
+ CloseHandle(hChildStdoutWr);
+
+ /* Read output from the child process. */
+ *pi_data = 0;
+ *pp_data = malloc( 1025 ); /* +1 for \0 */
+
+ while ( !p_object->b_die )
+ {
+ DWORD i_read;
+ if ( !ReadFile( hChildStdoutRd, &(*pp_data)[*pi_data], 1024, &i_read,
+ NULL )
+ || i_read == 0 )
+ break;
+ *pi_data += i_read;
+ *pp_data = realloc( *pp_data, *pi_data + 1025 );
+ }
+
+ while ( !p_object->b_die
+ && !GetExitCodeProcess( piProcInfo.hProcess, &i_status )
+ && i_status != STILL_ACTIVE )
+ msleep( 10000 );
+
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+
+ if ( i_status )
+ msg_Warn( p_object,
+ "child %s returned with error code %ld",
+ ppsz_argv[0], i_status );
+
+#else
+ msg_Err( p_object, "vlc_execve called but no implementation is available" );
+ return -1;
+
+#endif
+
+ (*pp_data)[*pi_data] = '\0';
+
+ return 0;
+}