Made percent_escape more general.

Added regression tests support to jnlib.
W32 changes.
This commit is contained in:
Werner Koch 2007-06-19 09:11:11 +00:00
parent e47321829d
commit 540f9164c0
18 changed files with 551 additions and 56 deletions

View File

@ -128,6 +128,9 @@ GnuPG.
The RPM specs file scripts/gnupg.spec has been contributed by
several people.
The function build_argv in agent/w32main.c is based on code from
Alexandre Julliard.
Copyright
=========

View File

@ -5,10 +5,14 @@
2007-06-18 Werner Koch <wk@g10code.com>
* w32main.c (build_argv): New.
(WinMain): Use it.
* command.c (cmd_killagent) [W32]: New.
(cmd_getinfo): New.
* gpg-agent.c (get_agent_ssh_socket_name): New.
(no_force_standard_socket) New.
(create_server_socket): Use it.
* Makefile.am (gpg_agent_res_ldflags): Pass windows option to ld.
2007-06-14 Werner Koch <wk@g10code.com>

View File

@ -93,6 +93,7 @@ enum cmd_and_opt_values
oMinPassphraseLen,
oUseStandardSocket,
oNoUseStandardSocket,
oNoReuseStandardSocket,
oIgnoreCacheForSigning,
oAllowMarkTrusted,
@ -130,6 +131,7 @@ static ARGPARSE_OPTS opts[] = {
{ oUseStandardSocket, "use-standard-socket", 0,
N_("use a standard location for the socket")},
{ oNoUseStandardSocket, "no-use-standard-socket", 0, "@"},
{ oNoReuseStandardSocket, "no-reuse-standard-socket", 0, "@"},
{ oPinentryProgram, "pinentry-program", 2 ,
N_("|PGM|use PGM as the PIN-Entry program") },
@ -186,6 +188,10 @@ static char *socket_name;
/* Name of the communication socket used for ssh-agent-emulation. */
static char *socket_name_ssh;
/* If set to true and a standard socket is requested, we won't try to
bind to a socket which is already in use. */
static int no_reuse_standard_socket;
/* Default values for options passed to the pinentry. */
static char *default_display;
static char *default_ttyname;
@ -215,7 +221,7 @@ static pid_t parent_pid = (pid_t)(-1);
static char *create_socket_name (int use_standard_socket,
char *standard_name, char *template);
static int create_server_socket (int is_standard_name, const char *name);
static int create_server_socket (int is_standard_name, char *name);
static void create_directories (void);
static void agent_init_default_ctrl (ctrl_t ctrl);
@ -621,6 +627,7 @@ main (int argc, char **argv )
case oUseStandardSocket: standard_socket = 1; break;
case oNoUseStandardSocket: standard_socket = 0; break;
case oNoReuseStandardSocket: no_reuse_standard_socket = 1; break;
case oKeepTTY: opt.keep_tty = 1; break;
case oKeepDISPLAY: opt.keep_display = 1; break;
@ -715,7 +722,7 @@ main (int argc, char **argv )
#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
filename = make_filename (opt.homedir, "gpg-agent.conf", NULL );
filename_esc = percent_escape (filename);
filename_esc = percent_escape (filename, NULL);
printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n",
GC_OPT_FLAG_DEFAULT, filename_esc);
@ -1229,7 +1236,7 @@ create_socket_name (int use_standard_socket,
whether a non-random socket is used. Returns the file descriptor or
terminates the process in case of an error. */
static int
create_server_socket (int is_standard_name, const char *name)
create_server_socket (int is_standard_name, char *name)
{
struct sockaddr_un *serv_addr;
socklen_t len;
@ -1257,14 +1264,16 @@ create_server_socket (int is_standard_name, const char *name)
#ifdef HAVE_W32_SYSTEM
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
if (is_standard_name && rc == -1 )
if (is_standard_name && rc == -1 && errno == WSAEADDRINUSE
&& !no_reuse_standard_socket)
{
remove (name);
rc = bind (fd, (struct sockaddr*) serv_addr, len);
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
}
#else
rc = bind (fd, (struct sockaddr*) serv_addr, len);
if (is_standard_name && rc == -1 && errno == EADDRINUSE)
if (is_standard_name && rc == -1 && errno == EADDRINUSE
&& !no_reuse_standard_socket)
{
remove (name);
rc = bind (fd, (struct sockaddr*) serv_addr, len);
@ -1272,9 +1281,15 @@ create_server_socket (int is_standard_name, const char *name)
#endif
if (rc == -1)
{
/* We use gpg_strerror here because it allows us to get strings
for some W32 socket error codes. */
log_error (_("error binding socket to `%s': %s\n"),
serv_addr->sun_path, strerror (errno));
serv_addr->sun_path,
gpg_strerror (gpg_error_from_errno (errno)));
close (fd);
if (is_standard_name && no_reuse_standard_socket)
*name = 0; /* Inhibit removal of the socket by cleanup(). */
agent_exit (2);
}

View File

@ -1,5 +1,6 @@
/* w32main.c - W32 main entry pint and taskbar support for the GnuPG Agent
* Copyright (C) 2007 Free Software Foundation, Inc.
* Copyright 1996, 1998 Alexandre Julliard
*
* This file is part of GnuPG.
*
@ -37,6 +38,136 @@ static HINSTANCE glob_hinst;
static HWND glob_hwnd;
/* Build an argv array from the command in CMDLINE. RESERVED is the
number of args to reserve before the first one. This code is based
on Alexandre Julliard's LGPLed wine-0.9.34/dlls/kernel32/process.c
and modified to fit into our framework. The function returns NULL
on error; on success an arry with the argiments is returned. This
array has been allocaqted using a plain malloc (and not the usual
xtrymalloc). */
static char **
build_argv (char *cmdline_arg, int reserved)
{
int argc;
char **argv;
char *cmdline, *s, *arg, *d;
int in_quotes, bs_count;
cmdline = malloc (strlen (cmdline_arg) + 1);
if (!cmdline)
return NULL;
strcpy (cmdline, cmdline_arg);
/* First determine the required size of the array. */
argc = reserved + 1;
bs_count = 0;
in_quotes = 0;
s = cmdline;
for (;;)
{
if ( !*s || ((*s==' ' || *s=='\t') && !in_quotes)) /* A space. */
{
argc++;
/* Skip the remaining spaces. */
while (*s==' ' || *s=='\t')
s++;
if (!*s)
break;
bs_count = 0;
}
else if (*s=='\\')
{
bs_count++;
s++;
}
else if ( (*s == '\"') && !(bs_count & 1))
{
/* Unescaped '\"' */
in_quotes = !in_quotes;
bs_count=0;
s++;
}
else /* A regular character. */
{
bs_count = 0;
s++;
}
}
argv = malloc (argc * sizeof *argv);
if (!argv)
{
free (cmdline);
return NULL;
}
/* Now actually parse the command line. */
argc = reserved;
bs_count = 0;
in_quotes=0;
arg = d = s = cmdline;
while (*s)
{
if ((*s==' ' || *s=='\t') && !in_quotes)
{
/* Close the argument and copy it. */
*d = 0;
argv[argc++] = arg;
/* Skip the remaining spaces. */
do
s++;
while (*s==' ' || *s=='\t');
/* Start with a new argument */
arg = d = s;
bs_count = 0;
}
else if (*s=='\\')
{
*d++ = *s++;
bs_count++;
}
else if (*s=='\"')
{
if ( !(bs_count & 1) )
{
/* Preceded by an even number of backslashes, this is
half that number of backslashes, plus a '\"' which we
discard. */
d -= bs_count/2;
s++;
in_quotes = !in_quotes;
}
else
{
/* Preceded by an odd number of backslashes, this is
half that number of backslashes followed by a '\"'. */
d = d - bs_count/2 - 1;
*d++ ='\"';
s++;
}
bs_count=0;
}
else /* A regular character. */
{
*d++ = *s++;
bs_count = 0;
}
}
if (*arg)
{
*d = 0;
argv[argc++] = arg;
}
argv[argc] = NULL;
return argv;
}
/* Our window message processing function. */
static LRESULT CALLBACK
wndw_proc (HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
@ -160,19 +291,18 @@ w32_setup_taskbar (void)
int WINAPI
WinMain (HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int showcmd)
{
/* Fixme: We need a parser for the command line. Should be
available in some CRT code - need to see whether we can find a
GNU version. For nopw we call gpg-agent with a couple of fixed arguments
*/
char *argv[] = { "gpg-agent.exe", "--daemon", "-v", "--debug-all", NULL };
char **argv;
int argc;
/* We use the GetCommandLine function because that also includes the
program name in contrast to the CMDLINE arg. */
argv = build_argv (GetCommandLineA (), 0);
if (!argv)
return 2; /* Can't do much about a malloc failure. */
for (argc=0; argv[argc]; argc++)
;
glob_hinst = hinst;
return w32_main (DIM(argv)-1, argv);
return w32_main (argc, argv);
}

View File

@ -369,18 +369,20 @@ this option at runtime does not kill an already forked scdaemon.
@item --use-standard-socket
@itemx --no-use-standard-socket
@itemx --no-reuse-standard-socket
@opindex use-standard-socket
@opindex no-use-standard-socket
@opindex no-reuse-standard-socket
By enabling this option @command{gpg-agent} will listen on the socket
named @file{S.gpg-agent}, located in the home directory, and not create
a random socket below a temporary directory. Tools connecting to
@command{gpg-agent} should first try to connect to the socket given in
environment variable @var{GPG_AGENT_INFO} and the fall back to this
socket. This option may not be used if the home directory is mounted as
a remote file system.
@noindent
Note, that as of now, W32 systems default to this option.
a remote file system. If @option{--no-reuse-standard-socket} is used,
@command{gpg-agent} will not try to reuse a socket which is already in
use. Note, that @option{--use-standard-socket} is the default on
Windows systems.
@item --display @var{string}

View File

@ -1456,7 +1456,7 @@ list_config(char *items)
static void
gpgconf_list (const char *configfile)
{
char *configfile_esc = percent_escape (configfile);
char *configfile_esc = percent_escape (configfile, NULL);
/* The following definitions are taken from gnupg/tools/gpgconf-comp.c. */
#define GC_OPT_FLAG_NONE 0UL

View File

@ -1,3 +1,17 @@
2007-06-19 Werner Koch <wk@g10code.com>
* Makefile.am: Add support for regression tests.
* t-support.h, t-support.c: New.
* t-stringhelp.c: New.
* stringhelp.c (percent_escape): Add arg EXTRA to make it a more
general function. Changed all callers.
2007-06-18 Werner Koch <wk@g10code.com>
* w32-afunix.c (_w32_sock_bind): Changed to properly detect an
already used socket.
2007-06-18 Marcus Brinkmann <marcus@g10code.de>
* stringhelp.h (percent_escape): New prototype.

View File

@ -23,6 +23,8 @@
## Process this file with automake to produce Makefile.in
EXTRA_DIST = README
noinst_PROGRAMS = $(module_tests)
TESTS = $(module_tests)
AM_CPPFLAGS = -I$(top_srcdir)/intl
@ -51,3 +53,20 @@ endif
# For GnuPG we don't need the xmalloc stuff.
# xmalloc.c xmalloc.h
#
# Module tests.
#
# These tests should only be used at the canonical location of jnlib
# which is the GnuPG package. The reason for this is that t-support.c
# defines replacements for the actual used memory allocation functions
# so that there is no dependency on libgcrypt.
#
module_tests = t-stringhelp
t_jnlib_src = t-support.c t-support.h
t_jnlib_ldadd = libjnlib.a $(LIBINTL) $(LIBICONV)
t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src)
t_stringhelp_LDADD = $(t_jnlib_ldadd)

View File

@ -34,6 +34,8 @@
#include "stringhelp.h"
#define tohex_lower(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'a'))
/*
* Look for the substring SUB in buffer and return a pointer to that
* substring in BUFFER or NULL if not found.
@ -827,19 +829,19 @@ memrchr (const void *buffer, int c, size_t n)
#endif /*HAVE_MEMRCHR*/
/* Percent-escape the string STR by replacing colons with '%3a'. */
/* Percent-escape the string STR by replacing colons with '%3a'. If
EXTRA is not NULL all characters in it are also escaped. */
char *
percent_escape (const char *str)
percent_escape (const char *str, const char *extra)
{
int i = 0;
int j = 0;
int i, j;
char *ptr;
if (!str)
return NULL;
while (str[i])
if (str[i++] == ':')
for (i=j=0; str[i]; i++)
if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
j++;
ptr = jnlib_xmalloc (i + 2 * j + 1);
i = 0;
@ -851,6 +853,18 @@ percent_escape (const char *str)
ptr[i++] = '3';
ptr[i++] = 'a';
}
else if (*str == '%')
{
ptr[i++] = '%';
ptr[i++] = '2';
ptr[i++] = '5';
}
else if (extra && strchr (extra, *str))
{
ptr[i++] = '%';
ptr[i++] = tohex_lower ((*str>>4)&15);
ptr[i++] = tohex_lower (*str&15);
}
else
ptr[i++] = *str;
str++;

View File

@ -117,8 +117,9 @@ isascii (int c)
#endif
#define STR2(v) STR(v)
/* Percent-escape the string STR by replacing colons with '%3a'. */
char *percent_escape (const char *str);
/* Percent-escape the string STR by replacing colons with '%3a'. If
EXTRA is not NULL, also replace all characters given in EXTRA. */
char *percent_escape (const char *str, const char *extra);
#endif /*LIBJNLIB_STRINGHELP_H*/

94
jnlib/t-stringhelp.c Normal file
View File

@ -0,0 +1,94 @@
/* t-stringhelp.c - Regression tests for stringhelp.c
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This file is part of JNLIB.
*
* JNLIB is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JNLIB 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stringhelp.h"
#include "t-support.h"
static void
test_percent_escape (void)
{
char *result;
static struct {
const char *extra;
const char *value;
const char *expected;
} tests[] =
{
{ NULL, "", "" },
{ NULL, "%", "%25" },
{ NULL, "%%", "%25%25" },
{ NULL, " %", " %25" },
{ NULL, ":", "%3a" },
{ NULL, " :", " %3a" },
{ NULL, ": ", "%3a " },
{ NULL, " : ", " %3a " },
{ NULL, "::", "%3a%3a" },
{ NULL, ": :", "%3a %3a" },
{ NULL, "%:", "%25%3a" },
{ NULL, ":%", "%3a%25" },
{ "\\\n:", ":%", "%3a%25" },
{ "\\\n:", "\\:%", "%5c%3a%25" },
{ "\\\n:", "\n:%", "%0a%3a%25" },
{ "\\\n:", "\xff:%", "\xff%3a%25" },
{ "\\\n:", "\xfe:%", "\xfe%3a%25" },
{ "\\\n:", "\x01:%", "\x01%3a%25" },
{ "\x01", "\x01:%", "%01%3a%25" },
{ "\xfe", "\xfe:%", "%fe%3a%25" },
{ "\xfe", "\xff:%", "\xff%3a%25" },
{ NULL, NULL, NULL }
};
int testno;
result = percent_escape (NULL, NULL);
if (result)
fail (0);
for (testno=0; tests[testno].value; testno++)
{
result = percent_escape (tests[testno].value, tests[testno].extra);
if (!result)
fail (testno);
if (strcmp (result, tests[testno].expected))
fail (testno);
xfree (result);
}
}
int
main (int argc, char **argv)
{
test_percent_escape ();
return 0;
}

111
jnlib/t-support.c Normal file
View File

@ -0,0 +1,111 @@
/* t-support.c - helper functions for the regression tests.
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This file is part of JNLIB.
*
* JNLIB is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JNLIB 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "t-support.h"
/* Replacements for the malloc functions as used here. */
static void
out_of_memory (void)
{
fprintf (stderr,"error: out of core in regression tests: %s\n",
strerror (errno));
exit (2);
}
void *
gcry_malloc (size_t n)
{
return malloc (n);
}
void *
gcry_xmalloc (size_t n)
{
void *p = malloc (n);
if (!p)
out_of_memory ();
return p;
}
char *
gcry_strdup (const char *string)
{
return malloc (strlen (string)+1);
}
void *
gcry_realloc (void *a, size_t n)
{
return realloc (a, n);
}
void *
gcry_xrealloc (void *a, size_t n)
{
void *p = realloc (a, n);
if (!p)
out_of_memory ();
return p;
}
void *
gcry_calloc (size_t n, size_t m)
{
return calloc (n, m);
}
void *
gcry_xcalloc (size_t n, size_t m)
{
void *p = calloc (n, m);
if (!p)
out_of_memory ();
return p;
}
char *
gcry_xstrdup (const char *string)
{
void *p = malloc (strlen (string)+1);
if (!p)
out_of_memory ();
strcpy (p, string);
return p;
}
void
gcry_free (void *a)
{
if (a)
free (a);
}

52
jnlib/t-support.h Normal file
View File

@ -0,0 +1,52 @@
/* t-support.h - Helper for the regression tests
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* This file is part of JNLIB.
*
* JNLIB is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JNLIB 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
*/
#ifndef LIBJNLIB_T_SUPPORT_H
#define LIBJNLIB_T_SUPPORT_H 1
#ifdef GCRYPT_VERSION
#error The regression tests should not include with gcrypt.h
#endif
/* Repalcement prototypes. */
void *gcry_xmalloc (size_t n);
void *gcry_xcalloc (size_t n, size_t m);
void *gcry_xrealloc (void *a, size_t n);
char *gcry_xstrdup (const char * a);
void gcry_free (void *a);
/* Map the used xmalloc functions to those implemented by t-support.c */
#define xmalloc(a) gcry_xmalloc ( (a) )
#define xcalloc(a,b) gcry_xcalloc ( (a), (b) )
#define xrealloc(a,n) gcry_xrealloc ( (a), (n) )
#define xstrdup(a) gcry_xstrdup ( (a) )
#define xfree(a) gcry_free ( (a) )
/* Macros to print the result of a test. */
#define pass() do { ; } while(0)
#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
__FILE__,__LINE__, (a)); \
exit (1); \
} while(0)
#endif /*LIBJNLIB_T_SUPPORT_H*/

View File

@ -22,11 +22,19 @@
#ifdef _WIN32
#include <stdio.h>
#include <windows.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <io.h>
#include <errno.h>
#include "w32-afunix.h"
#ifndef S_IRGRP
# define S_IRGRP 0
# define S_IWGRP 0
#endif
int
_w32_close (int fd)
{
@ -87,28 +95,50 @@ _w32_sock_bind (int sockfd, struct sockaddr * addr, int addrlen)
{
struct sockaddr_in myaddr;
struct sockaddr_un *unaddr;
int filefd;
FILE *fp;
int len = sizeof myaddr;
int rc;
unaddr = (struct sockaddr_un *)addr;
myaddr.sin_port = 0;
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
filefd = open (unaddr->sun_path,
(O_WRONLY|O_CREAT|O_EXCL|O_BINARY),
(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
if (filefd == -1)
{
if (errno == EEXIST)
errno = WSAEADDRINUSE;
return -1;
}
fp = fdopen (filefd, "wb");
if (!fp)
{
int save_e = errno;
close (filefd);
errno = save_e;
return -1;
}
rc = bind (sockfd, (struct sockaddr *)&myaddr, len);
if (rc)
return rc;
if (!rc)
rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len);
if (rc)
{
int save_e = errno;
fclose (fp);
remove (unaddr->sun_path);
errno = save_e;
return rc;
unaddr = (struct sockaddr_un *)addr;
fp = fopen (unaddr->sun_path, "wb");
if (!fp)
return -1;
}
fprintf (fp, "%d", myaddr.sin_port);
fclose (fp);
/* we need this later. */
/* The caller expects these values. */
unaddr->sun_family = myaddr.sin_family;
unaddr->sun_port = myaddr.sin_port;
unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;

View File

@ -551,7 +551,7 @@ main (int argc, char **argv )
#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
if (!config_filename)
filename = make_filename (opt.homedir, "scdaemon.conf", NULL );
filename_esc = percent_escape (filename);
filename_esc = percent_escape (filename, NULL);
printf ("gpgconf-scdaemon.conf:%lu:\"%s\n",
GC_OPT_FLAG_DEFAULT, filename_esc);

View File

@ -1393,7 +1393,7 @@ main ( int argc, char **argv)
a default, which is described by the value of the ARGDEF field. */
#define GC_OPT_FLAG_NO_ARG_DESC (1UL << 6)
char *config_filename_esc = percent_escape (opt.config_filename);
char *config_filename_esc = percent_escape (opt.config_filename, NULL);
printf ("gpgconf-gpgsm.conf:%lu:\"%s\n",
GC_OPT_FLAG_DEFAULT, config_filename_esc);

View File

@ -1,3 +1,8 @@
2007-06-19 Werner Koch <wk@g10code.com>
* gpgconf-comp.c (percent_escape): Rename to my_percent_escape.
Changed all callers.
2007-06-18 Marcus Brinkmann <marcus@g10code.de>
* gpgconf-comp.c (retrieve_options_from_file): Close LIST_FILE.

View File

@ -984,7 +984,7 @@ my_dgettext (const char *domain, const char *msgid)
/* Percent-Escape special characters. The string is valid until the
next invocation of the function. */
static char *
percent_escape (const char *src)
my_percent_escape (const char *src)
{
static char *esc_str;
static int esc_str_len;
@ -1083,7 +1083,8 @@ gc_component_list_components (FILE *out)
{
const char *desc = gc_component[idx].desc;
desc = my_dgettext (gc_component[idx].desc_domain, desc);
fprintf (out, "%s:%s\n", gc_component[idx].name, percent_escape (desc));
fprintf (out, "%s:%s\n",
gc_component[idx].name, my_percent_escape (desc));
}
}
@ -1174,7 +1175,7 @@ list_one_option (const gc_option_t *option, FILE *out)
fprintf (out, " %s", gc_level[option->level].name);
/* The description field. */
fprintf (out, ":%s", desc ? percent_escape (desc) : "");
fprintf (out, ":%s", desc ? my_percent_escape (desc) : "");
/* The type field. */
fprintf (out, ":%u", option->arg_type);
@ -1188,7 +1189,7 @@ list_one_option (const gc_option_t *option, FILE *out)
gc_arg_type[gc_arg_type[option->arg_type].fallback].name);
/* The argument name field. */
fprintf (out, ":%s", arg_name ? percent_escape (arg_name) : "");
fprintf (out, ":%s", arg_name ? my_percent_escape (arg_name) : "");
if (arg_name)
xfree (arg_name);
@ -1458,7 +1459,7 @@ retrieve_options_from_program (gc_component_t component, gc_backend_t backend)
}
else if (gc_arg_type[option->arg_type].fallback
== GC_ARG_TYPE_STRING)
opt_value = xasprintf ("\"%s", percent_escape (value));
opt_value = xasprintf ("\"%s", my_percent_escape (value));
else
{
/* FIXME: Verify that the number is sane. */
@ -1549,12 +1550,12 @@ retrieve_options_from_file (gc_component_t component, gc_backend_t backend)
really append. */
if (list)
{
new_list = xasprintf ("%s,\"%s", list, percent_escape (start));
new_list = xasprintf ("%s,\"%s", list, my_percent_escape (start));
xfree (list);
list = new_list;
}
else
list = xasprintf ("\"%s", percent_escape (start));
list = xasprintf ("\"%s", my_percent_escape (start));
}
if (length < 0 || ferror (list_file))
gc_error (1, errno, "can not read list file %s", list_pathname);