From: Rémi Denis-Courmont Date: Sun, 24 Aug 2008 09:42:39 +0000 (+0300) Subject: Revert "Don't mess with the build system a single day (git revert 83b35c64b6e1f7c90b5... X-Git-Tag: 0.9.0~41 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=2c364f7a23dcea11d5e1c6fcb39130e66a4579db;p=vlc Revert "Don't mess with the build system a single day (git revert 83b35c64b6e1f7c90b577724d3e3a1fa57b7b747 -n!) before a major (git revert 83b35c64b6e1f7c90b577724d3e3a1fa57b7b747 -n) release" Unbreak Linux build. This reverts commit f806629f32ed6d19dc510983348653c29a227441. --- diff --git a/Makefile.am b/Makefile.am index 4e2fd2364e..162883f49c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -7,7 +7,7 @@ # which have makefiles with distribution information. # - src (libvlc) is nedeed by modules, mozilla and bindings # - libs/* are needed by modules -BASE_SUBDIRS = po src modules share doc test +BASE_SUBDIRS = po src bin modules share doc test EXTRA_SUBDIRS = m4 extras/package/ipkg \ libs/loader libs/srtp \ projects/mozilla projects/activex @@ -20,6 +20,9 @@ endif if HAVE_LIBGCRYPT SUBDIRS += libs/srtp endif +if BUILD_VLC +SUBDIRS += bin +endif SUBDIRS += modules share doc test if BUILD_MOZILLA SUBDIRS += projects/mozilla @@ -313,8 +316,8 @@ DISTCLEANFILES = $(BUILT_SOURCES_distclean) vlc-config.in compile ChangeLog libvlc: cd src && $(MAKE) $(AM_MAKEFLAGS) libvlccore.la -core: - cd src && $(MAKE) $(AM_MAKEFLAGS) vlc$(EXEEXT) +core: libvlc + cd bin && $(MAKE) $(AM_MAKEFLAGS) vlc$(EXEEXT) doc: cd doc && $(MAKE) $(AM_MAKEFLAGS) doc @@ -389,7 +392,7 @@ endif vlc$(EXEEXT): Makefile.am rm -f -- vlc vlc.tmp echo '#! /bin/sh' > vlc.tmp - echo 'exec "$$(dirname "$$0")/src/vlc$(EXEEXT)" "--plugin-path=$$(dirname "$$0")/modules" "$$@"' >> vlc.tmp + echo 'exec "$$(dirname "$$0")/bin/vlc$(EXEEXT)" "--plugin-path=$$(dirname "$$0")/modules" "$$@"' >> vlc.tmp chmod +x vlc.tmp mv -f -- vlc.tmp vlc diff --git a/bin/Makefile.am b/bin/Makefile.am new file mode 100644 index 0000000000..141bb422b8 --- /dev/null +++ b/bin/Makefile.am @@ -0,0 +1,41 @@ +# Building vlc +# +bin_PROGRAMS = vlc +EXTRA_PROGRAMS = vlc-wrapper + +if !HAVE_WIN32 +bin_PROGRAMS += vlc-wrapper +endif + +EXTRA_vlc_SOURCES = vlc.c winvlc.c +if !HAVE_WIN32 +vlc_SOURCES = vlc.c +else +vlc_SOURCES = winvlc.c +endif +vlc_wrapper_SOURCES = rootwrap.c + +vlc_DEPENDENCIES = $(DATA_win32_rc) ../src/libvlc.la + +vlc_CFLAGS = `$(VLC_CONFIG) --cflags vlc` +vlc_LDFLAGS = `$(VLC_CONFIG) --ldflags vlc` +# vlc needs libvlccore for locale conversion +vlc_LDADD = ../src/libvlc.la ../src/libvlccore.la $(LTLIBINTL) \ + `$(VLC_CONFIG) -libs vlc` + +#vlc$(EXEEXT): $(vlc_OBJECTS) $(vlc_DEPENDENCIES) +# $(LINK) $(vlc_OBJECTS) $(vlc_LDADD) $(vlc_LDFLAGS) + +DATA_win32_rc = vlc_win32_rc.$(OBJEXT) +DATA_win32_rc_lib = libvlc_win32_rc.$(OBJEXT) +EXTRA_DATA = $(DATA_win32_rc) $(DATA_win32_rc_lib) +if HAVE_WIN32 +vlc_LDADD += $(DATA_win32_rc) +noinst_DATA = $(DATA_win32_rc) $(DATA_win32_rc_lib) +endif + +vlc_win32_rc.$(OBJEXT): $(top_builddir)/share/vlc_win32_rc.rc + $(WINDRES) --include-dir $(top_srcdir)/share -i $< -o $@ + +libvlc_win32_rc.$(OBJEXT): $(top_builddir)/share/libvlc_win32_rc.rc + $(WINDRES) --include-dir $(top_srcdir)/share -i $< -o $@ diff --git a/bin/rootwrap.c b/bin/rootwrap.c new file mode 100644 index 0000000000..f2c851a354 --- /dev/null +++ b/bin/rootwrap.c @@ -0,0 +1,240 @@ +/***************************************************************************** + * rootwrap.c + ***************************************************************************** + * Copyright © 2005-2008 Rémi Denis-Courmont + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#if HAVE_CONFIG_H +# include +#endif + +#include /* exit() */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include /* getrlimit() */ +#include +#include +#include + +#if defined (AF_INET6) && !defined (IPV6_V6ONLY) +# warning Uho, your IPv6 support is broken and has been disabled. Fix your C library. +# undef AF_INET6 +#endif + +#ifndef AF_LOCAL +# define AF_LOCAL AF_UNIX +#endif + +static inline int is_allowed_port (uint16_t port) +{ + port = ntohs (port); + return (port == 80) || (port == 443) || (port == 554); +} + + +static inline int send_err (int fd, int err) +{ + return send (fd, &err, sizeof (err), 0) == sizeof (err) ? 0 : -1; +} + +/** + * Send a file descriptor to another process + */ +static int send_fd (int p, int fd) +{ + struct msghdr hdr; + struct iovec iov; + struct cmsghdr *cmsg; + char buf[CMSG_SPACE (sizeof (fd))]; + int val = 0; + + hdr.msg_name = NULL; + hdr.msg_namelen = 0; + hdr.msg_iov = &iov; + hdr.msg_iovlen = 1; + hdr.msg_control = buf; + hdr.msg_controllen = sizeof (buf); + + iov.iov_base = &val; + iov.iov_len = sizeof (val); + + cmsg = CMSG_FIRSTHDR (&hdr); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof (fd)); + memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd)); + hdr.msg_controllen = cmsg->cmsg_len; + + return sendmsg (p, &hdr, 0) == sizeof (val) ? 0 : -1; +} + + +/** + * Background process run as root to open privileged TCP ports. + */ +static void rootprocess (int fd) +{ + struct sockaddr_storage ss; + + while (recv (fd, &ss, sizeof (ss), 0) == sizeof (ss)) + { + unsigned len; + int sock; + + switch (ss.ss_family) + { + case AF_INET: + if (!is_allowed_port (((struct sockaddr_in *)&ss)->sin_port)) + { + if (send_err (fd, EACCES)) + return; + continue; + } + len = sizeof (struct sockaddr_in); + break; + +#ifdef AF_INET6 + case AF_INET6: + if (!is_allowed_port (((struct sockaddr_in6 *)&ss)->sin6_port)) + { + if (send_err (fd, EACCES)) + return; + continue; + } + len = sizeof (struct sockaddr_in6); + break; +#endif + + default: + if (send_err (fd, EAFNOSUPPORT)) + return; + continue; + } + + sock = socket (ss.ss_family, SOCK_STREAM, IPPROTO_TCP); + if (sock != -1) + { + const int val = 1; + + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof (val)); +#ifdef AF_INET6 + if (ss.ss_family == AF_INET6) + setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof (val)); +#endif + if (bind (sock, (struct sockaddr *)&ss, len) == 0) + { + send_fd (fd, sock); + close (sock); + continue; + } + } + send_err (fd, errno); + } +} + +/* TODO? + * - use libcap if available, + * - call chroot + */ + +int main (int argc, char *argv[]) +{ + /* Support for dynamically opening RTSP, HTTP and HTTP/SSL ports */ + int pair[2]; + + if (socketpair (AF_LOCAL, SOCK_STREAM, 0, pair)) + return 1; + if (pair[0] < 3) + goto error; /* we want 0, 1 and 2 open */ + + pid_t pid = fork (); + switch (pid) + { + case -1: + goto error; + + case 0: + { + int null = open ("/dev/null", O_RDWR); + if (null != -1) + { + dup2 (null, 0); + dup2 (null, 1); + dup2 (null, 2); + close (null); + } + close (pair[0]); + setsid (); + rootprocess (pair[1]); + exit (0); + } + } + + close (pair[1]); + pair[1] = -1; + + char buf[21]; + snprintf (buf, sizeof (buf), "%d", pair[0]); + setenv ("VLC_ROOTWRAP_SOCK", buf, 1); + + /* Support for real-time priorities */ +#ifdef RLIMIT_RTPRIO + struct rlimit rlim; + rlim.rlim_max = rlim.rlim_cur = sched_get_priority_min (SCHED_RR) + 24; + setrlimit (RLIMIT_RTPRIO, &rlim); +#endif + + uid_t uid = getuid (); + if (uid == 0) + { + const char *sudo = getenv ("SUDO_UID"); + if (sudo) + uid = atoi (sudo); + } + if (uid == 0) + { + fprintf (stderr, "Cannot determine unprivileged user for VLC!\n"); + exit (1); + } + setuid (uid); + + if (!setuid (0)) /* sanity check: we cannot get root back */ + exit (1); + + /* Yeah, the user can execute just about anything from here. + * But we've dropped privileges, so it does not matter. */ + if (strlen (argv[0]) < sizeof ("-wrapper")) + goto error; + argv[0][strlen (argv[0]) - strlen ("-wrapper")] = '\0'; + + (void)argc; + if (execvp (argv[0], argv)) + perror (argv[0]); + +error: + close (pair[0]); + if (pair[1] != -1) + close (pair[1]); + return 1; +} diff --git a/bin/vlc.c b/bin/vlc.c new file mode 100644 index 0000000000..2ede9433e4 --- /dev/null +++ b/bin/vlc.c @@ -0,0 +1,155 @@ +/***************************************************************************** + * vlc.c: the VLC player + ***************************************************************************** + * Copyright (C) 1998-2008 the VideoLAN team + * $Id$ + * + * Authors: Vincent Seguin + * Samuel Hocevar + * Gildas Bazin + * Derk-Jan Hartman + * Lots of other people, see the libvlc AUTHORS file + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + + +/* Explicit HACK */ +extern void LocaleFree (const char *); +extern char *FromLocale (const char *); + +#include +#include +#include +#include + +/***************************************************************************** + * main: parse command line, start interface and spawn threads. + *****************************************************************************/ +int main( int i_argc, const char *ppsz_argv[] ) +{ + int i_ret; + + if (geteuid () == 0) + { + fprintf (stderr, "VLC is not supposed to be run as root. Sorry.\n" + "If you need to use real-time priorities and/or privileged TCP ports\n" + "you can use %s-wrapper (make sure it is Set-UID root first and\n" + "cannot be run by non-trusted users first).\n", ppsz_argv[0]); + return 1; + } + + setlocale (LC_ALL, ""); + +#ifndef __APPLE__ + /* This clutters OSX GUI error logs */ + fprintf( stderr, "VLC media player %s\n", libvlc_get_version() ); +#endif + +#ifdef HAVE_PUTENV +# ifndef NDEBUG + /* Activate malloc checking routines to detect heap corruptions. */ + putenv( (char*)"MALLOC_CHECK_=2" ); +# ifdef __APPLE__ + putenv( (char*)"MallocErrorAbort=crash_my_baby_crash" ); +# endif + + /* Disable the ugly Gnome crash dialog so that we properly segfault */ + putenv( (char *)"GNOME_DISABLE_CRASH_DIALOG=1" ); +# endif +#endif + +#if defined (HAVE_GETEUID) && !defined (SYS_BEOS) + /* FIXME: rootwrap (); */ +#endif + + /* Synchronously intercepted POSIX signals. + * + * In a threaded program such as VLC, the only sane way to handle signals + * is to block them in all thread but one - this is the only way to + * predict which thread will receive them. If any piece of code depends + * on delivery of one of this signal it is intrinsically not thread-safe + * and MUST NOT be used in VLC, whether we like it or not. + * There is only one exception: if the signal is raised with + * pthread_kill() - we do not use this in LibVLC but some pthread + * implementations use them internally. You should really use conditions + * for thread synchronization anyway. + * + * Signal that request a clean shutdown, and force an unclean shutdown + * if they are triggered again 2+ seconds later. + * We have to handle SIGTERM cleanly because of daemon mode. + * Note that we set the signals after the vlc_create call. */ + static const int sigs[] = { + SIGINT, SIGHUP, SIGQUIT, SIGTERM, + /* Signals that cause a no-op: + * - SIGPIPE might happen with sockets and would crash VLC. It MUST be + * blocked by any LibVLC-dependent application, in addition to VLC. + * - SIGCHLD is comes after exec*() (such as httpd CGI support) and must + * be dequeued to cleanup zombie processes. + */ + SIGPIPE, SIGCHLD + }; + + sigset_t set; + sigemptyset (&set); + for (unsigned i = 0; i < sizeof (sigs) / sizeof (sigs[0]); i++) + sigaddset (&set, sigs[i]); + + /* Block all these signals */ + pthread_sigmask (SIG_BLOCK, &set, NULL); + + /* Note that FromLocale() can be used before libvlc is initialized */ + for (int i = 0; i < i_argc; i++) + if ((ppsz_argv[i] = FromLocale (ppsz_argv[i])) == NULL) + return 1; // BOOM! + + libvlc_exception_t ex, dummy; + libvlc_exception_init (&ex); + libvlc_exception_init (&dummy); + + /* Initialize libvlc */ + int i_argc_real = i_argc ? i_argc - 1 : 0; + const char **ppsz_argv_real = i_argc ? &ppsz_argv[1] : ppsz_argv; + libvlc_instance_t *vlc = libvlc_new (i_argc_real, ppsz_argv_real, &ex); + + if (vlc != NULL) + { + libvlc_add_intf (vlc, "signals", &dummy); + libvlc_add_intf (vlc, NULL, &ex); + libvlc_playlist_play (vlc, -1, 0, NULL, &dummy); + libvlc_wait (vlc); + libvlc_release (vlc); + } + i_ret = libvlc_exception_raised (&ex); + if( i_ret ) + fprintf( stderr, "%s\n", libvlc_exception_get_message( &ex)); + + libvlc_exception_clear (&ex); + libvlc_exception_clear (&dummy); + + for (int i = 0; i < i_argc; i++) + LocaleFree (ppsz_argv[i]); + + return i_ret; +} diff --git a/bin/winvlc.c b/bin/winvlc.c new file mode 100644 index 0000000000..18c1b13b12 --- /dev/null +++ b/bin/winvlc.c @@ -0,0 +1,136 @@ +/***************************************************************************** + * winvlc.c: the Windows VLC player + ***************************************************************************** + * Copyright (C) 1998-2008 the VideoLAN team + * + * Authors: Vincent Seguin + * Samuel Hocevar + * Gildas Bazin + * Derk-Jan Hartman + * Lots of other people, see the libvlc AUTHORS file + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define UNICODE +#include +#include +#include +#include +#include + +static int parse_cmdline (char *line, char ***argvp) +{ + char **argv = malloc (sizeof (char *)); + int argc = 0; + + while (*line != '\0') + { + char quote = 0; + + /* Skips white spaces */ + while (strchr ("\t ", *line)) + line++; + if (!*line) + break; + + /* Starts a new parameter */ + argv = realloc (argv, (argc + 2) * sizeof (char *)); + if (*line == '"') + { + quote = '"'; + line++; + } + argv[argc++] = line; + + more: + while (*line && !strchr ("\t ", *line)) + line++; + + if (line > argv[argc - 1] && line[-1] == quote) + /* End of quoted parameter */ + line[-1] = 0; + else + if (*line && quote) + { + /* Space within a quote */ + line++; + goto more; + } + else + /* End of unquoted parameter */ + if (*line) + *line++ = 0; + } + argv[argc] = NULL; + *argvp = argv; + return argc; +} + +#ifdef UNDER_CE +# define wWinMain WinMain +#endif + +/***************************************************************************** + * wWinMain: parse command line, start interface and spawn threads. + *****************************************************************************/ +int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, int nCmdShow ) +{ + char **argv, psz_cmdline[wcslen(lpCmdLine) * 4 + 1]; + int argc, ret; + + (void)hInstance; (void)hPrevInstance; (void)nCmdShow; + + WideCharToMultiByte( CP_UTF8, 0, lpCmdLine, -1, + psz_cmdline, sizeof (psz_cmdline), NULL, NULL ); + + argc = parse_cmdline (psz_cmdline, &argv); + + libvlc_exception_t ex, dummy; + libvlc_exception_init (&ex); + libvlc_exception_init (&dummy); + + /* Initialize libvlc */ + libvlc_instance_t *vlc = libvlc_new (argc, (const char **)argv, &ex); + if (vlc != NULL) + { + libvlc_add_intf (vlc, NULL, &ex); + libvlc_playlist_play (vlc, -1, 0, NULL, &dummy); + libvlc_wait (vlc); + libvlc_release (vlc); + } + free (argv); + + ret = libvlc_exception_raised (&ex); + libvlc_exception_clear (&ex); + libvlc_exception_clear (&dummy); + return ret; +} + +#ifndef IF_MINGW_SUPPORTED_UNICODE +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR args, int nCmdShow) +{ + /* This makes little sense, but at least it links properly */ + wchar_t lpCmdLine[(strlen (args) + 1) * 3]; + MultiByteToWideChar (CP_ACP, 0, args, -1, lpCmdLine, sizeof (lpCmdLine)); + return wWinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow); +} +#endif diff --git a/configure.ac b/configure.ac index de300d49cd..83430cdf6a 100644 --- a/configure.ac +++ b/configure.ac @@ -5861,6 +5861,7 @@ AC_CONFIG_FILES([ share/libvlc_win32_rc.rc src/Makefile src/test/Makefile + bin/Makefile test/Makefile ])