mirror of https://github.com/n-hys/bash.git
200 lines
3.9 KiB
C
200 lines
3.9 KiB
C
/* fnxform - use iconv(3) to transform strings to and from "filename" format */
|
|
|
|
/* Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
|
|
|
This file is part of GNU Bash, the Bourne Again SHell.
|
|
|
|
Bash 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 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Bash 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 Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#if defined (HAVE_UNISTD_H)
|
|
# include <unistd.h>
|
|
#endif
|
|
#include "bashansi.h"
|
|
#include <stdio.h>
|
|
#include "bashtypes.h"
|
|
|
|
#include "stdc.h"
|
|
#include "bashintl.h"
|
|
#include <xmalloc.h>
|
|
|
|
#if defined (HAVE_ICONV)
|
|
# include <iconv.h>
|
|
#endif
|
|
|
|
#if defined (HAVE_LOCALE_CHARSET)
|
|
extern const char *locale_charset PARAMS((void));
|
|
#else
|
|
extern char *get_locale_var PARAMS((char *));
|
|
#endif
|
|
|
|
#if defined (HAVE_ICONV)
|
|
static iconv_t conv_fromfs = (iconv_t)-1;
|
|
static iconv_t conv_tofs = (iconv_t)-1;
|
|
|
|
#define OUTLEN_MAX 4096
|
|
|
|
static char *outbuf = 0;
|
|
static size_t outlen = 0;
|
|
|
|
static char *curencoding PARAMS((void));
|
|
static void init_tofs PARAMS((void));
|
|
static void init_fromfs PARAMS((void));
|
|
|
|
static char *
|
|
curencoding ()
|
|
{
|
|
char *loc;
|
|
#if defined (HAVE_LOCALE_CHARSET)
|
|
loc = (char *)locale_charset ();
|
|
return loc;
|
|
#else
|
|
char *dot, *mod;
|
|
|
|
loc = get_locale_var ("LC_CTYPE");
|
|
if (loc == 0 || *loc == 0)
|
|
return "";
|
|
dot = strchr (loc, '.');
|
|
if (dot == 0)
|
|
return loc;
|
|
mod = strchr (dot, '@');
|
|
if (mod)
|
|
*mod = '\0';
|
|
return ++dot;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
init_tofs ()
|
|
{
|
|
char *cur;
|
|
|
|
cur = curencoding ();
|
|
conv_tofs = iconv_open ("UTF-8-MAC", cur);
|
|
}
|
|
|
|
static void
|
|
init_fromfs ()
|
|
{
|
|
char *cur;
|
|
|
|
cur = curencoding ();
|
|
conv_fromfs = iconv_open (cur, "UTF-8-MAC");
|
|
}
|
|
|
|
char *
|
|
fnx_tofs (string, len)
|
|
char *string;
|
|
size_t len;
|
|
{
|
|
#ifdef MACOSX
|
|
ICONV_CONST char *inbuf;
|
|
char *tempbuf;
|
|
size_t templen;
|
|
|
|
if (conv_tofs == (iconv_t)-1)
|
|
init_tofs ();
|
|
if (conv_tofs == (iconv_t)-1)
|
|
return string;
|
|
|
|
/* Free and reallocate outbuf if it's *too* big */
|
|
if (outlen >= OUTLEN_MAX && len < OUTLEN_MAX - 8)
|
|
{
|
|
free (outbuf);
|
|
outbuf = 0;
|
|
outlen = 0;
|
|
}
|
|
|
|
inbuf = string;
|
|
if (outbuf == 0 || outlen < len + 8)
|
|
{
|
|
outlen = len + 8;
|
|
outbuf = outbuf ? xrealloc (outbuf, outlen + 1) : xmalloc (outlen + 1);
|
|
}
|
|
tempbuf = outbuf;
|
|
templen = outlen;
|
|
|
|
iconv (conv_tofs, NULL, NULL, NULL, NULL);
|
|
|
|
if (iconv (conv_tofs, &inbuf, &len, &tempbuf, &templen) == (size_t)-1)
|
|
return string;
|
|
|
|
*tempbuf = '\0';
|
|
return outbuf;
|
|
#else
|
|
return string;
|
|
#endif
|
|
}
|
|
|
|
char *
|
|
fnx_fromfs (string, len)
|
|
char *string;
|
|
size_t len;
|
|
{
|
|
#ifdef MACOSX
|
|
ICONV_CONST char *inbuf;
|
|
char *tempbuf;
|
|
size_t templen;
|
|
|
|
if (conv_fromfs == (iconv_t)-1)
|
|
init_fromfs ();
|
|
if (conv_fromfs == (iconv_t)-1)
|
|
return string;
|
|
|
|
/* Free and reallocate outbuf if it's *too* big */
|
|
if (outlen >= OUTLEN_MAX && len < OUTLEN_MAX - 8)
|
|
{
|
|
free (outbuf);
|
|
outbuf = 0;
|
|
outlen = 0;
|
|
}
|
|
|
|
inbuf = string;
|
|
if (outbuf == 0 || outlen < (len + 8))
|
|
{
|
|
outlen = len + 8;
|
|
outbuf = outbuf ? xrealloc (outbuf, outlen + 1) : xmalloc (outlen + 1);
|
|
}
|
|
tempbuf = outbuf;
|
|
templen = outlen;
|
|
|
|
iconv (conv_fromfs, NULL, NULL, NULL, NULL);
|
|
|
|
if (iconv (conv_fromfs, &inbuf, &len, &tempbuf, &templen) == (size_t)-1)
|
|
return string;
|
|
|
|
*tempbuf = '\0';
|
|
return outbuf;
|
|
#else
|
|
return string;
|
|
#endif
|
|
}
|
|
|
|
#else
|
|
char *
|
|
fnx_tofs (string)
|
|
char *string;
|
|
{
|
|
return string;
|
|
}
|
|
|
|
char *
|
|
fnx_fromfs (string)
|
|
char *string;
|
|
{
|
|
return string;
|
|
}
|
|
#endif
|