libc.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:29k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * libc.c: Extra libc function for some systems.
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2006 the VideoLAN team
  5.  * $Id: ada9f6e2ed1b717e3009b9e0db50ca55e141d33d $
  6.  *
  7.  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  8.  *          Samuel Hocevar <sam@zoy.org>
  9.  *          Gildas Bazin <gbazin@videolan.org>
  10.  *          Derk-Jan Hartman <hartman at videolan dot org>
  11.  *          Christophe Massiot <massiot@via.ecp.fr>
  12.  *          Rémi Denis-Courmont <rem à videolan.org>
  13.  *
  14.  * This program is free software; you can redistribute it and/or modify
  15.  * it under the terms of the GNU General Public License as published by
  16.  * the Free Software Foundation; either version 2 of the License, or
  17.  * (at your option) any later version.
  18.  *
  19.  * This program is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22.  * GNU General Public License for more details.
  23.  *
  24.  * You should have received a copy of the GNU General Public License
  25.  * along with this program; if not, write to the Free Software
  26.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  27.  *****************************************************************************/
  28. #ifdef HAVE_CONFIG_H
  29. # include "config.h"
  30. #endif
  31. #include <vlc_common.h>
  32. #include <ctype.h>
  33. #undef iconv_t
  34. #undef iconv_open
  35. #undef iconv
  36. #undef iconv_close
  37. #if defined(HAVE_ICONV)
  38. #   include <iconv.h>
  39. #endif
  40. #ifdef HAVE_DIRENT_H
  41. #   include <dirent.h>
  42. #endif
  43. #ifdef HAVE_FORK
  44. #   include <signal.h>
  45. #   include <sys/time.h>
  46. #   include <unistd.h>
  47. #   include <errno.h>
  48. #   include <sys/wait.h>
  49. #   include <fcntl.h>
  50. #   include <sys/socket.h>
  51. #   include <sys/poll.h>
  52. #   ifndef PF_LOCAL
  53. #       define PF_LOCAL PF_UNIX
  54. #   endif
  55. #endif
  56. #if defined(WIN32) || defined(UNDER_CE)
  57. #   undef _wopendir
  58. #   undef _wreaddir
  59. #   undef _wclosedir
  60. #   undef rewinddir
  61. #   define WIN32_LEAN_AND_MEAN
  62. #   include <windows.h>
  63. #endif
  64. /*****************************************************************************
  65.  * vlc_*dir_wrapper: wrapper under Windows to return the list of drive letters
  66.  * when called with an empty argument or just ''
  67.  *****************************************************************************/
  68. #if defined(WIN32)
  69. #   include <assert.h>
  70. typedef struct vlc_DIR
  71. {
  72.     _WDIR *p_real_dir;
  73.     int i_drives;
  74.     struct _wdirent dd_dir;
  75.     bool b_insert_back;
  76. } vlc_DIR;
  77. void *vlc_wopendir( const wchar_t *wpath )
  78. {
  79.     vlc_DIR *p_dir = NULL;
  80.     _WDIR *p_real_dir = NULL;
  81.     if ( wpath == NULL || wpath[0] == ''
  82.           || (wcscmp (wpath, L"\") == 0) )
  83.     {
  84.         /* Special mode to list drive letters */
  85.         p_dir = malloc( sizeof(vlc_DIR) );
  86.         if( !p_dir )
  87.             return NULL;
  88.         p_dir->p_real_dir = NULL;
  89. #if defined(UNDER_CE)
  90.         p_dir->i_drives = NULL;
  91. #else
  92.         p_dir->i_drives = GetLogicalDrives();
  93. #endif
  94.         return (void *)p_dir;
  95.     }
  96.     p_real_dir = _wopendir( wpath );
  97.     if ( p_real_dir == NULL )
  98.         return NULL;
  99.     p_dir = malloc( sizeof(vlc_DIR) );
  100.     if( !p_dir )
  101.     {
  102.         _wclosedir( p_real_dir );
  103.         return NULL;
  104.     }
  105.     p_dir->p_real_dir = p_real_dir;
  106.     assert (wpath[0]); // wpath[1] is defined
  107.     p_dir->b_insert_back = !wcscmp (wpath + 1, L":\");
  108.     return (void *)p_dir;
  109. }
  110. struct _wdirent *vlc_wreaddir( void *_p_dir )
  111. {
  112.     vlc_DIR *p_dir = (vlc_DIR *)_p_dir;
  113.     DWORD i_drives;
  114.     if ( p_dir->p_real_dir != NULL )
  115.     {
  116.         if ( p_dir->b_insert_back )
  117.         {
  118.             /* Adds "..", gruik! */
  119.             p_dir->dd_dir.d_ino = 0;
  120.             p_dir->dd_dir.d_reclen = 0;
  121.             p_dir->dd_dir.d_namlen = 2;
  122.             wcscpy( p_dir->dd_dir.d_name, L".." );
  123.             p_dir->b_insert_back = false;
  124.             return &p_dir->dd_dir;
  125.         }
  126.         return _wreaddir( p_dir->p_real_dir );
  127.     }
  128.     /* Drive letters mode */
  129.     i_drives = p_dir->i_drives;
  130. #ifdef UNDER_CE
  131.     swprintf( p_dir->dd_dir.d_name, L"\");
  132.     p_dir->dd_dir.d_namlen = wcslen(p_dir->dd_dir.d_name);
  133. #else
  134.     unsigned int i;
  135.     if ( !i_drives )
  136.         return NULL; /* end */
  137.     for ( i = 0; i < sizeof(DWORD)*8; i++, i_drives >>= 1 )
  138.         if ( i_drives & 1 ) break;
  139.     if ( i >= 26 )
  140.         return NULL; /* this should not happen */
  141.     swprintf( p_dir->dd_dir.d_name, L"%c:\", 'A' + i );
  142.     p_dir->dd_dir.d_namlen = wcslen(p_dir->dd_dir.d_name);
  143.     p_dir->i_drives &= ~(1UL << i);
  144. #endif
  145.     return &p_dir->dd_dir;
  146. }
  147. void vlc_rewinddir( void *_p_dir )
  148. {
  149.     vlc_DIR *p_dir = (vlc_DIR *)_p_dir;
  150.     if ( p_dir->p_real_dir != NULL )
  151.         _wrewinddir( p_dir->p_real_dir );
  152. }
  153. #endif
  154. /* This one is in the libvlccore exported symbol list */
  155. int vlc_wclosedir( void *_p_dir )
  156. {
  157. #if defined(WIN32)
  158.     vlc_DIR *p_dir = (vlc_DIR *)_p_dir;
  159.     int i_ret = 0;
  160.     if ( p_dir->p_real_dir != NULL )
  161.         i_ret = _wclosedir( p_dir->p_real_dir );
  162.     free( p_dir );
  163.     return i_ret;
  164. #else
  165.     return closedir( _p_dir );
  166. #endif
  167. }
  168. #ifdef ENABLE_NLS
  169. # include <libintl.h>
  170. #endif
  171. /**
  172.  * In-tree plugins share their gettext domain with LibVLC.
  173.  */
  174. char *vlc_gettext( const char *msgid )
  175. {
  176. #ifdef ENABLE_NLS
  177.     return dgettext( PACKAGE_NAME, msgid );
  178. #else
  179.     return (char *)msgid;
  180. #endif
  181. }
  182. /*****************************************************************************
  183.  * Local conversion routine from ISO_6937 to UTF-8 charset. Support for this
  184.  * is still missing in libiconv, hence multiple operating systems lack it.
  185.  * The conversion table adds Euro sign (0xA4) as per ETSI EN 300 468 Annex A
  186.  *****************************************************************************/
  187. #ifndef __linux__
  188. static const uint16_t to_ucs4[128] =
  189. {
  190.   /* 0x80 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  191.   /* 0x88 */ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  192.   /* 0x90 */ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  193.   /* 0x98 */ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  194.   /* 0xa0 */ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0000, 0x00a7,
  195.   /* 0xa8 */ 0x00a4, 0x2018, 0x201c, 0x00ab, 0x2190, 0x2191, 0x2192, 0x2193,
  196.   /* 0xb0 */ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00d7, 0x00b5, 0x00b6, 0x00b7,
  197.   /* 0xb8 */ 0x00f7, 0x2019, 0x201d, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  198.   /* 0xc0 */ 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
  199.   /* 0xc8 */ 0xffff, 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff,
  200.   /* 0xd0 */ 0x2014, 0x00b9, 0x00ae, 0x00a9, 0x2122, 0x266a, 0x00ac, 0x00a6,
  201.   /* 0xd8 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e,
  202.   /* 0xe0 */ 0x2126, 0x00c6, 0x00d0, 0x00aa, 0x0126, 0x0000, 0x0132, 0x013f,
  203.   /* 0xe8 */ 0x0141, 0x00d8, 0x0152, 0x00ba, 0x00de, 0x0166, 0x014a, 0x0149,
  204.   /* 0xf0 */ 0x0138, 0x00e6, 0x0111, 0x00f0, 0x0127, 0x0131, 0x0133, 0x0140,
  205.   /* 0xf8 */ 0x0142, 0x00f8, 0x0153, 0x00df, 0x00fe, 0x0167, 0x014b, 0x00ad
  206. };
  207. /* The outer array range runs from 0xc1 to 0xcf, the inner range from 0x40
  208.    to 0x7f.  */
  209. static const uint16_t to_ucs4_comb[15][64] =
  210. {
  211.   /* 0xc1 */
  212.   {
  213.     /* 0x40 */ 0x0000, 0x00c0, 0x0000, 0x0000, 0x0000, 0x00c8, 0x0000, 0x0000,
  214.     /* 0x48 */ 0x0000, 0x00cc, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d2,
  215.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d9, 0x0000, 0x0000,
  216.     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  217.     /* 0x60 */ 0x0000, 0x00e0, 0x0000, 0x0000, 0x0000, 0x00e8, 0x0000, 0x0000,
  218.     /* 0x68 */ 0x0000, 0x00ec, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f2,
  219.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f9, 0x0000, 0x0000,
  220.     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  221.   },
  222.   /* 0xc2 */
  223.   {
  224.     /* 0x40 */ 0x0000, 0x00c1, 0x0000, 0x0106, 0x0000, 0x00c9, 0x0000, 0x0000,
  225.     /* 0x48 */ 0x0000, 0x00cd, 0x0000, 0x0000, 0x0139, 0x0000, 0x0143, 0x00d3,
  226.     /* 0x50 */ 0x0000, 0x0000, 0x0154, 0x015a, 0x0000, 0x00da, 0x0000, 0x0000,
  227.     /* 0x58 */ 0x0000, 0x00dd, 0x0179, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  228.     /* 0x60 */ 0x0000, 0x00e1, 0x0000, 0x0107, 0x0000, 0x00e9, 0x0000, 0x0000,
  229.     /* 0x68 */ 0x0000, 0x00ed, 0x0000, 0x0000, 0x013a, 0x0000, 0x0144, 0x00f3,
  230.     /* 0x70 */ 0x0000, 0x0000, 0x0155, 0x015b, 0x0000, 0x00fa, 0x0000, 0x0000,
  231.     /* 0x78 */ 0x0000, 0x00fd, 0x017a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  232.   },
  233.   /* 0xc3 */
  234.   {
  235.     /* 0x40 */ 0x0000, 0x00c2, 0x0000, 0x0108, 0x0000, 0x00ca, 0x0000, 0x011c,
  236.     /* 0x48 */ 0x0124, 0x00ce, 0x0134, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d4,
  237.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x015c, 0x0000, 0x00db, 0x0000, 0x0174,
  238.     /* 0x58 */ 0x0000, 0x0176, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  239.     /* 0x60 */ 0x0000, 0x00e2, 0x0000, 0x0109, 0x0000, 0x00ea, 0x0000, 0x011d,
  240.     /* 0x68 */ 0x0125, 0x00ee, 0x0135, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f4,
  241.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x015d, 0x0000, 0x00fb, 0x0000, 0x0175,
  242.     /* 0x78 */ 0x0000, 0x0177, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  243.   },
  244.   /* 0xc4 */
  245.   {
  246.     /* 0x40 */ 0x0000, 0x00c3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  247.     /* 0x48 */ 0x0000, 0x0128, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d1, 0x00d5,
  248.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0168, 0x0000, 0x0000,
  249.     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  250.     /* 0x60 */ 0x0000, 0x00e3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  251.     /* 0x68 */ 0x0000, 0x0129, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f1, 0x00f5,
  252.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0169, 0x0000, 0x0000,
  253.     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  254.   },
  255.   /* 0xc5 */
  256.   {
  257.     /* 0x40 */ 0x0000, 0x0100, 0x0000, 0x0000, 0x0000, 0x0112, 0x0000, 0x0000,
  258.     /* 0x48 */ 0x0000, 0x012a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x014c,
  259.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016a, 0x0000, 0x0000,
  260.     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  261.     /* 0x60 */ 0x0000, 0x0101, 0x0000, 0x0000, 0x0000, 0x0113, 0x0000, 0x0000,
  262.     /* 0x68 */ 0x0000, 0x012b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x014d,
  263.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016b, 0x0000, 0x0000,
  264.     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  265.   },
  266.   /* 0xc6 */
  267.   {
  268.     /* 0x40 */ 0x0000, 0x0102, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x011e,
  269.     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  270.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x0000, 0x0000,
  271.     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  272.     /* 0x60 */ 0x0000, 0x0103, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x011f,
  273.     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  274.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x0000, 0x0000,
  275.     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  276.   },
  277.   /* 0xc7 */
  278.   {
  279.     /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x010a, 0x0000, 0x0116, 0x0000, 0x0120,
  280.     /* 0x48 */ 0x0000, 0x0130, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  281.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  282.     /* 0x58 */ 0x0000, 0x0000, 0x017b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  283.     /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x010b, 0x0000, 0x0117, 0x0000, 0x0121,
  284.     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  285.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  286.     /* 0x78 */ 0x0000, 0x0000, 0x017c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  287.   },
  288.   /* 0xc8 */
  289.   {
  290.     /* 0x40 */ 0x0000, 0x00c4, 0x0000, 0x0000, 0x0000, 0x00cb, 0x0000, 0x0000,
  291.     /* 0x48 */ 0x0000, 0x00cf, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d6,
  292.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00dc, 0x0000, 0x0000,
  293.     /* 0x58 */ 0x0000, 0x0178, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  294.     /* 0x60 */ 0x0000, 0x00e4, 0x0000, 0x0000, 0x0000, 0x00eb, 0x0000, 0x0000,
  295.     /* 0x68 */ 0x0000, 0x00ef, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00f6,
  296.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00fc, 0x0000, 0x0000,
  297.     /* 0x78 */ 0x0000, 0x00ff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  298.   },
  299.   /* 0xc9 */
  300.   {
  301.     0x0000,
  302.   },
  303.   /* 0xca */
  304.   {
  305.     /* 0x40 */ 0x0000, 0x00c5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  306.     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  307.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016e, 0x0000, 0x0000,
  308.     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  309.     /* 0x60 */ 0x0000, 0x00e5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  310.     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  311.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x016f, 0x0000, 0x0000,
  312.     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  313.   },
  314.   /* 0xcb */
  315.   {
  316.     /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x00c7, 0x0000, 0x0000, 0x0000, 0x0122,
  317.     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0136, 0x013b, 0x0000, 0x0145, 0x0000,
  318.     /* 0x50 */ 0x0000, 0x0000, 0x0156, 0x015e, 0x0162, 0x0000, 0x0000, 0x0000,
  319.     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  320.     /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x00e7, 0x0000, 0x0000, 0x0000, 0x0123,
  321.     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0137, 0x013c, 0x0000, 0x0146, 0x0000,
  322.     /* 0x70 */ 0x0000, 0x0000, 0x0157, 0x015f, 0x0163, 0x0000, 0x0000, 0x0000,
  323.     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  324.   },
  325.   /* 0xcc */
  326.   {
  327.     0x0000,
  328.   },
  329.   /* 0xcd */
  330.   {
  331.     /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  332.     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0150,
  333.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0170, 0x0000, 0x0000,
  334.     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  335.     /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  336.     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0151,
  337.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0171, 0x0000, 0x0000,
  338.     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  339.   },
  340.   /* 0xce */
  341.   {
  342.     /* 0x40 */ 0x0000, 0x0104, 0x0000, 0x0000, 0x0000, 0x0118, 0x0000, 0x0000,
  343.     /* 0x48 */ 0x0000, 0x012e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  344.     /* 0x50 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0172, 0x0000, 0x0000,
  345.     /* 0x58 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  346.     /* 0x60 */ 0x0000, 0x0105, 0x0000, 0x0000, 0x0000, 0x0119, 0x0000, 0x0000,
  347.     /* 0x68 */ 0x0000, 0x012f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  348.     /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0173, 0x0000, 0x0000,
  349.     /* 0x78 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  350.   },
  351.   /* 0xcf */
  352.   {
  353.     /* 0x40 */ 0x0000, 0x0000, 0x0000, 0x010c, 0x010e, 0x011a, 0x0000, 0x0000,
  354.     /* 0x48 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x013d, 0x0000, 0x0147, 0x0000,
  355.     /* 0x50 */ 0x0000, 0x0000, 0x0158, 0x0160, 0x0164, 0x0000, 0x0000, 0x0000,
  356.     /* 0x58 */ 0x0000, 0x0000, 0x017d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
  357.     /* 0x60 */ 0x0000, 0x0000, 0x0000, 0x010d, 0x010f, 0x011b, 0x0000, 0x0000,
  358.     /* 0x68 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x013e, 0x0000, 0x0148, 0x0000,
  359.     /* 0x70 */ 0x0000, 0x0000, 0x0159, 0x0161, 0x0165, 0x0000, 0x0000, 0x0000,
  360.     /* 0x78 */ 0x0000, 0x0000, 0x017e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
  361.   }
  362. };
  363. static size_t ISO6937toUTF8( const unsigned char **inbuf, size_t *inbytesleft,
  364.                              unsigned char **outbuf, size_t *outbytesleft )
  365. {
  366.     if( !inbuf || !(*inbuf) )
  367.         return (size_t)(0);    /* Reset state requested */
  368.     const unsigned char *iptr = *inbuf;
  369.     const unsigned char *iend = iptr + *inbytesleft;
  370.     unsigned char *optr = *outbuf;
  371.     unsigned char *oend = optr + *outbytesleft;
  372.     uint16_t ch;
  373.     int err = 0;
  374.     while ( iptr < iend )
  375.     {
  376.         if( *iptr < 0x80 )
  377.         {
  378.             if( optr >= oend )
  379.             {
  380.                 err = E2BIG;
  381.                 break;    /* No space in outbuf */
  382.             }
  383.             *optr++ = *iptr++;
  384.             continue;
  385.         }
  386.         if ( optr + 2 >= oend )
  387.         {
  388.             err = E2BIG;
  389.             break;        /* No space in outbuf for multibyte char */
  390.         }
  391.         ch = to_ucs4[*iptr - 0x80];
  392.         if( ch == 0xffff )
  393.         {
  394.             /* Composed character */
  395.             if ( iptr + 1 >= iend )
  396.             {
  397.                 err = EINVAL;
  398.                 break;    /* No next character */
  399.             }
  400.             if ( iptr[1] < 0x40 || iptr[1] >= 0x80 ||
  401.                  !(ch = to_ucs4_comb[iptr[0] - 0xc1][iptr[1] - 0x40]) )
  402.             {
  403.                 err = EILSEQ;
  404.                 break;   /* Illegal combination */
  405.             }
  406.             iptr += 2;
  407.         }
  408.         else
  409.         {
  410.             if ( !ch )
  411.             {
  412.                 err = EILSEQ;
  413.                 break;
  414.             }
  415.             iptr++;
  416.         }
  417.         if ( ch < 0x800 )
  418.         {
  419.             optr[1] = 0x80 | (ch & 0x3f);
  420.             optr[0] = 0xc0 | (ch >> 6);
  421.             optr +=2;
  422.         }
  423.         else
  424.         {
  425.             optr[2] = 0x80 | (ch & 0x3f);
  426.             ch >>= 6;
  427.             optr[1] = 0x80 | (ch & 0x3f);
  428.             optr[0] = 0xe0 | (ch >> 6);
  429.             optr += 3;
  430.         }
  431.     }
  432.     *inbuf = iptr;
  433.     *outbuf = optr;
  434.     *inbytesleft = iend - iptr;
  435.     *outbytesleft = oend - optr;
  436.     if( err )
  437.     {
  438.         errno = err;
  439.         return (size_t)(-1);
  440.     }
  441.     return (size_t)(0);
  442. }
  443. #endif
  444. /*****************************************************************************
  445.  * iconv wrapper
  446.  *****************************************************************************/
  447. vlc_iconv_t vlc_iconv_open( const char *tocode, const char *fromcode )
  448. {
  449. #ifndef __linux__
  450.     if( !strcasecmp(tocode, "UTF-8") && !strcasecmp(fromcode, "ISO_6937") )
  451.         return (vlc_iconv_t)(-2);
  452. #endif
  453. #if defined(HAVE_ICONV)
  454.     return iconv_open( tocode, fromcode );
  455. #else
  456.     return (vlc_iconv_t)(-1);
  457. #endif
  458. }
  459. size_t vlc_iconv( vlc_iconv_t cd, const char **inbuf, size_t *inbytesleft,
  460.                   char **outbuf, size_t *outbytesleft )
  461. {
  462. #ifndef __linux__
  463.     if ( cd == (vlc_iconv_t)(-2) )
  464.         return ISO6937toUTF8( (const unsigned char **)inbuf, inbytesleft,
  465.                               (unsigned char **)outbuf, outbytesleft );
  466. #endif
  467. #if defined(HAVE_ICONV)
  468.     return iconv( cd, (ICONV_CONST char **)inbuf, inbytesleft,
  469.                   outbuf, outbytesleft );
  470. #else
  471.     abort ();
  472. #endif
  473. }
  474. int vlc_iconv_close( vlc_iconv_t cd )
  475. {
  476. #ifndef __linux__
  477.     if ( cd == (vlc_iconv_t)(-2) )
  478.         return 0;
  479. #endif
  480. #if defined(HAVE_ICONV)
  481.     return iconv_close( cd );
  482. #else
  483.     abort ();
  484. #endif
  485. }
  486. /*****************************************************************************
  487.  * reduce a fraction
  488.  *   (adapted from libavcodec, author Michael Niedermayer <michaelni@gmx.at>)
  489.  *****************************************************************************/
  490. bool vlc_ureduce( unsigned *pi_dst_nom, unsigned *pi_dst_den,
  491.                         uint64_t i_nom, uint64_t i_den, uint64_t i_max )
  492. {
  493.     bool b_exact = 1;
  494.     uint64_t i_gcd;
  495.     if( i_den == 0 )
  496.     {
  497.         *pi_dst_nom = 0;
  498.         *pi_dst_den = 1;
  499.         return 1;
  500.     }
  501.     i_gcd = GCD( i_nom, i_den );
  502.     i_nom /= i_gcd;
  503.     i_den /= i_gcd;
  504.     if( i_max == 0 ) i_max = INT64_C(0xFFFFFFFF);
  505.     if( i_nom > i_max || i_den > i_max )
  506.     {
  507.         uint64_t i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
  508.         b_exact = 0;
  509.         for( ; ; )
  510.         {
  511.             uint64_t i_x = i_nom / i_den;
  512.             uint64_t i_a2n = i_x * i_a1_num + i_a0_num;
  513.             uint64_t i_a2d = i_x * i_a1_den + i_a0_den;
  514.             if( i_a2n > i_max || i_a2d > i_max ) break;
  515.             i_nom %= i_den;
  516.             i_a0_num = i_a1_num; i_a0_den = i_a1_den;
  517.             i_a1_num = i_a2n; i_a1_den = i_a2d;
  518.             if( i_nom == 0 ) break;
  519.             i_x = i_nom; i_nom = i_den; i_den = i_x;
  520.         }
  521.         i_nom = i_a1_num;
  522.         i_den = i_a1_den;
  523.     }
  524.     *pi_dst_nom = i_nom;
  525.     *pi_dst_den = i_den;
  526.     return b_exact;
  527. }
  528. /*************************************************************************
  529.  * vlc_execve: Execute an external program with a given environment,
  530.  * wait until it finishes and return its standard output
  531.  *************************************************************************/
  532. int __vlc_execve( vlc_object_t *p_object, int i_argc, char *const *ppsz_argv,
  533.                   char *const *ppsz_env, const char *psz_cwd,
  534.                   const char *p_in, size_t i_in,
  535.                   char **pp_data, size_t *pi_data )
  536. {
  537.     (void)i_argc; // <-- hmph
  538. #ifdef HAVE_FORK
  539. # define BUFSIZE 1024
  540.     int fds[2], i_status;
  541.     if (socketpair (PF_LOCAL, SOCK_STREAM, 0, fds))
  542.         return -1;
  543.     pid_t pid = -1;
  544.     if ((fds[0] > 2) && (fds[1] > 2))
  545.         pid = fork ();
  546.     switch (pid)
  547.     {
  548.         case -1:
  549.             msg_Err (p_object, "unable to fork (%m)");
  550.             close (fds[0]);
  551.             close (fds[1]);
  552.             return -1;
  553.         case 0:
  554.         {
  555.             sigset_t set;
  556.             sigemptyset (&set);
  557.             pthread_sigmask (SIG_SETMASK, &set, NULL);
  558.             /* NOTE:
  559.              * Like it or not, close can fail (and not only with EBADF)
  560.              */
  561.             if ((close (0) == 0) && (close (1) == 0) && (close (2) == 0)
  562.              && (dup (fds[1]) == 0) && (dup (fds[1]) == 1)
  563.              && (open ("/dev/null", O_RDONLY) == 2)
  564.              && ((psz_cwd == NULL) || (chdir (psz_cwd) == 0)))
  565.                 execve (ppsz_argv[0], ppsz_argv, ppsz_env);
  566.             exit (EXIT_FAILURE);
  567.         }
  568.     }
  569.     close (fds[1]);
  570.     *pi_data = 0;
  571.     if (*pp_data)
  572.         free (*pp_data);
  573.     *pp_data = NULL;
  574.     if (i_in == 0)
  575.         shutdown (fds[0], SHUT_WR);
  576.     while (!p_object->b_die)
  577.     {
  578.         struct pollfd ufd[1];
  579.         memset (ufd, 0, sizeof (ufd));
  580.         ufd[0].fd = fds[0];
  581.         ufd[0].events = POLLIN;
  582.         if (i_in > 0)
  583.             ufd[0].events |= POLLOUT;
  584.         if (poll (ufd, 1, 10) <= 0)
  585.             continue;
  586.         if (ufd[0].revents & ~POLLOUT)
  587.         {
  588.             char *ptr = realloc (*pp_data, *pi_data + BUFSIZE + 1);
  589.             if (ptr == NULL)
  590.                 break; /* safely abort */
  591.             *pp_data = ptr;
  592.             ssize_t val = read (fds[0], ptr + *pi_data, BUFSIZE);
  593.             switch (val)
  594.             {
  595.                 case -1:
  596.                 case 0:
  597.                     shutdown (fds[0], SHUT_RD);
  598.                     break;
  599.                 default:
  600.                     *pi_data += val;
  601.             }
  602.         }
  603.         if (ufd[0].revents & POLLOUT)
  604.         {
  605.             ssize_t val = write (fds[0], p_in, i_in);
  606.             switch (val)
  607.             {
  608.                 case -1:
  609.                 case 0:
  610.                     i_in = 0;
  611.                     shutdown (fds[0], SHUT_WR);
  612.                     break;
  613.                 default:
  614.                     i_in -= val;
  615.                     p_in += val;
  616.             }
  617.         }
  618.     }
  619.     close (fds[0]);
  620.     while (waitpid (pid, &i_status, 0) == -1);
  621.     if (WIFEXITED (i_status))
  622.     {
  623.         i_status = WEXITSTATUS (i_status);
  624.         if (i_status)
  625.             msg_Warn (p_object,  "child %s (PID %d) exited with error code %d",
  626.                       ppsz_argv[0], (int)pid, i_status);
  627.     }
  628.     else
  629.     if (WIFSIGNALED (i_status)) // <-- this should be redumdant a check
  630.     {
  631.         i_status = WTERMSIG (i_status);
  632.         msg_Warn (p_object, "child %s (PID %d) exited on signal %d (%s)",
  633.                   ppsz_argv[0], (int)pid, i_status, strsignal (i_status));
  634.     }
  635. #elif defined( WIN32 ) && !defined( UNDER_CE )
  636.     SECURITY_ATTRIBUTES saAttr;
  637.     PROCESS_INFORMATION piProcInfo;
  638.     STARTUPINFO siStartInfo;
  639.     BOOL bFuncRetn = FALSE;
  640.     HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr;
  641.     DWORD i_status;
  642.     char *psz_cmd = NULL, *p_env = NULL, *p = NULL;
  643.     char **ppsz_parser;
  644.     int i_size;
  645.     /* Set the bInheritHandle flag so pipe handles are inherited. */
  646.     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  647.     saAttr.bInheritHandle = TRUE;
  648.     saAttr.lpSecurityDescriptor = NULL;
  649.     /* Create a pipe for the child process's STDOUT. */
  650.     if ( !CreatePipe( &hChildStdoutRd, &hChildStdoutWr, &saAttr, 0 ) )
  651.     {
  652.         msg_Err( p_object, "stdout pipe creation failed" );
  653.         return -1;
  654.     }
  655.     /* Ensure the read handle to the pipe for STDOUT is not inherited. */
  656.     SetHandleInformation( hChildStdoutRd, HANDLE_FLAG_INHERIT, 0 );
  657.     /* Create a pipe for the child process's STDIN. */
  658.     if ( !CreatePipe( &hChildStdinRd, &hChildStdinWr, &saAttr, 0 ) )
  659.     {
  660.         msg_Err( p_object, "stdin pipe creation failed" );
  661.         return -1;
  662.     }
  663.     /* Ensure the write handle to the pipe for STDIN is not inherited. */
  664.     SetHandleInformation( hChildStdinWr, HANDLE_FLAG_INHERIT, 0 );
  665.     /* Set up members of the PROCESS_INFORMATION structure. */
  666.     ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
  667.     /* Set up members of the STARTUPINFO structure. */
  668.     ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
  669.     siStartInfo.cb = sizeof(STARTUPINFO);
  670.     siStartInfo.hStdError = hChildStdoutWr;
  671.     siStartInfo.hStdOutput = hChildStdoutWr;
  672.     siStartInfo.hStdInput = hChildStdinRd;
  673.     siStartInfo.wShowWindow = SW_HIDE;
  674.     siStartInfo.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  675.     /* Set up the command line. */
  676.     psz_cmd = malloc(32768);
  677.     if( !psz_cmd )
  678.         return -1;
  679.     psz_cmd[0] = '';
  680.     i_size = 32768;
  681.     ppsz_parser = &ppsz_argv[0];
  682.     while ( ppsz_parser[0] != NULL && i_size > 0 )
  683.     {
  684.         /* Protect the last argument with quotes ; the other arguments
  685.          * are supposed to be already protected because they have been
  686.          * passed as a command-line option. */
  687.         if ( ppsz_parser[1] == NULL )
  688.         {
  689.             strncat( psz_cmd, """, i_size );
  690.             i_size--;
  691.         }
  692.         strncat( psz_cmd, *ppsz_parser, i_size );
  693.         i_size -= strlen( *ppsz_parser );
  694.         if ( ppsz_parser[1] == NULL )
  695.         {
  696.             strncat( psz_cmd, """, i_size );
  697.             i_size--;
  698.         }
  699.         strncat( psz_cmd, " ", i_size );
  700.         i_size--;
  701.         ppsz_parser++;
  702.     }
  703.     /* Set up the environment. */
  704.     p = p_env = malloc(32768);
  705.     if( !p )
  706.     {
  707.         free( psz_cmd );
  708.         return -1;
  709.     }
  710.     i_size = 32768;
  711.     ppsz_parser = &ppsz_env[0];
  712.     while ( *ppsz_parser != NULL && i_size > 0 )
  713.     {
  714.         memcpy( p, *ppsz_parser,
  715.                 __MIN((int)(strlen(*ppsz_parser) + 1), i_size) );
  716.         p += strlen(*ppsz_parser) + 1;
  717.         i_size -= strlen(*ppsz_parser) + 1;
  718.         ppsz_parser++;
  719.     }
  720.     *p = '';
  721.     /* Create the child process. */
  722.     bFuncRetn = CreateProcess( NULL,
  723.           psz_cmd,       // command line
  724.           NULL,          // process security attributes
  725.           NULL,          // primary thread security attributes
  726.           TRUE,          // handles are inherited
  727.           0,             // creation flags
  728.           p_env,
  729.           psz_cwd,
  730.           &siStartInfo,  // STARTUPINFO pointer
  731.           &piProcInfo ); // receives PROCESS_INFORMATION
  732.     free( psz_cmd );
  733.     free( p_env );
  734.     if ( bFuncRetn == 0 )
  735.     {
  736.         msg_Err( p_object, "child creation failed" );
  737.         return -1;
  738.     }
  739.     /* Read from a file and write its contents to a pipe. */
  740.     while ( i_in > 0 && !p_object->b_die )
  741.     {
  742.         DWORD i_written;
  743.         if ( !WriteFile( hChildStdinWr, p_in, i_in, &i_written, NULL ) )
  744.             break;
  745.         i_in -= i_written;
  746.         p_in += i_written;
  747.     }
  748.     /* Close the pipe handle so the child process stops reading. */
  749.     CloseHandle(hChildStdinWr);
  750.     /* Close the write end of the pipe before reading from the
  751.      * read end of the pipe. */
  752.     CloseHandle(hChildStdoutWr);
  753.     /* Read output from the child process. */
  754.     *pi_data = 0;
  755.     if( *pp_data )
  756.         free( pp_data );
  757.     *pp_data = NULL;
  758.     *pp_data = malloc( 1025 );  /* +1 for  */
  759.     while ( !p_object->b_die )
  760.     {
  761.         DWORD i_read;
  762.         if ( !ReadFile( hChildStdoutRd, &(*pp_data)[*pi_data], 1024, &i_read,
  763.                         NULL )
  764.               || i_read == 0 )
  765.             break;
  766.         *pi_data += i_read;
  767.         *pp_data = realloc( *pp_data, *pi_data + 1025 );
  768.     }
  769.     while ( !p_object->b_die
  770.              && !GetExitCodeProcess( piProcInfo.hProcess, &i_status )
  771.              && i_status != STILL_ACTIVE )
  772.         msleep( 10000 );
  773.     CloseHandle(piProcInfo.hProcess);
  774.     CloseHandle(piProcInfo.hThread);
  775.     if ( i_status )
  776.         msg_Warn( p_object,
  777.                   "child %s returned with error code %ld",
  778.                   ppsz_argv[0], i_status );
  779. #else
  780.     msg_Err( p_object, "vlc_execve called but no implementation is available" );
  781.     return -1;
  782. #endif
  783.     if (*pp_data == NULL)
  784.         return -1;
  785.     (*pp_data)[*pi_data] = '';
  786.     return 0;
  787. }