/** \file wutil.c Wide character equivalents of various standard unix functions. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "common.h" #include "wutil.h" static char *tmp=0; static size_t tmp_len=0; int c = 0; void wutil_destroy() { free( tmp ); tmp=0; tmp_len=0; debug( 3, L"wutil functions called %d times", c ); } static char *wutil_wcs2str( const wchar_t *in ) { c++; size_t new_sz =MAX_UTF8_BYTES*wcslen(in)+1; if( tmp_len < new_sz ) { free( tmp ); tmp = malloc( new_sz ); if( !tmp ) { die_mem(); } tmp_len = new_sz; } wcstombs( tmp, in, tmp_len ); return tmp; } wchar_t *wgetcwd( wchar_t *buff, size_t sz ) { char buffc[sz*MAX_UTF8_BYTES]; char *res = getcwd( buffc, sz*MAX_UTF8_BYTES ); if( !res ) return 0; if( (size_t)-1 == mbstowcs( buff, buffc, sizeof( wchar_t ) * sz ) ) { return 0; } return buff; } int wchdir( const wchar_t * dir ) { char *tmp = wutil_wcs2str(dir); return chdir( tmp ); } FILE *wfopen(const wchar_t *path, const char *mode) { char *tmp =wutil_wcs2str(path); FILE *res=0; if( tmp ) { res = fopen(tmp, mode); } return res; } FILE *wfreopen(const wchar_t *path, const char *mode, FILE *stream) { char *tmp =wutil_wcs2str(path); FILE *res=0; if( tmp ) { res = freopen(tmp, mode, stream); } return res; } int wopen(const wchar_t *pathname, int flags, ...) { char *tmp =wutil_wcs2str(pathname); int res=-1; va_list argp; if( tmp ) { va_start( argp, flags ); if( ! (flags & O_CREAT) ) res = open(tmp, flags); else res = open(tmp, flags, va_arg(argp, int) ); va_end( argp ); } return res; } int wcreat(const wchar_t *pathname, mode_t mode) { char *tmp =wutil_wcs2str(pathname); int res = -1; if( tmp ) { res= creat(tmp, mode); } return res; } DIR *wopendir(const wchar_t *name) { char *tmp =wutil_wcs2str(name); DIR *res = 0; if( tmp ) { res = opendir(tmp); } return res; } int wstat(const wchar_t *file_name, struct stat *buf) { char *tmp =wutil_wcs2str(file_name); int res = -1; if( tmp ) { res = stat(tmp, buf); } return res; } int lwstat(const wchar_t *file_name, struct stat *buf) { char *tmp =wutil_wcs2str(file_name); int res = -1; if( tmp ) { res = lstat(tmp, buf); } return res; } int waccess(const wchar_t *file_name, int mode) { char *tmp =wutil_wcs2str(file_name); int res = -1; if( tmp ) { res= access(tmp, mode); } return res; } void wperror(const wchar_t *s) { if( s != 0 ) { fwprintf( stderr, L"%ls: ", s ); } fwprintf( stderr, L"%s\n", strerror( errno ) ); } #if !HAVE_WPRINTF /* Here is my own implementation of *wprintf, included since NetBSD does not provide one of it's own. */ /** This function is defined to help vgwprintf when it wants to call itself recursively */ static int gwprintf( void (*writer)(wchar_t), const wchar_t *filter, ... ); /** Generic formatting function. All other formatting functions are secretly a wrapper around this function. */ static int vgwprintf( void (*writer)(wchar_t), const wchar_t *filter, va_list va ) { const wchar_t *filter_org=filter; int count=0; for( ;*filter; filter++) { if(*filter == L'%') { int i; int is_long=0; int width = 0; filter++; int loop=1; int precision=INT_MAX; while( loop ) { switch(*filter) { case L'l': /* Long variable */ is_long++; filter++; break; case L'*': /* Set minimum field width */ width = va_arg( va, int ); filter++; break; case L'.': /* Set precision. Hasn't been tested enough yet, so I don't really trust it. */ filter++; if( *filter == L'*' ) { precision = va_arg( va, int ); } else { while( (*filter >= L'0') && (*filter <= L'9')) { precision=10*precision+(*filter - L'0'); } } break; default: loop=0; break; } } switch( *filter ) { case L'c': { wchar_t c; c = is_long?va_arg(va, wchar_t):btowc(va_arg(va, int)); if( width ) { int i; for( i=1; i