Better detect total failure of linker script generation.
[glibc.git] / libidn / idn-stub.c
blob3c69bbc3b3c08976821ec44cb2eb8450569961ba
1 /* idn-stub.c --- Stub to dlopen libcidn.so and invoke idna_to_ascii_lz.
2 * Copyright (C) 2003, 2004 Simon Josefsson
4 * This file is part of GNU Libidn.
6 * GNU Libidn is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * GNU Libidn is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with GNU Libidn; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <dlfcn.h>
26 #include <gnu/lib-names.h>
27 #include <bits/libc-lock.h>
29 /* Get specification for idna_to_ascii_lz. */
30 #include "idna.h"
32 /* Handle of the libidn DSO. */
33 static void *h;
36 static int (*to_ascii_lz) (const char *input, char **output, int flags);
37 static int (*to_unicode_lzlz) (const char *input, char **output, int flags);
40 static void
41 load_dso (void)
43 /* Lock protecting the DSO loading. */
44 __libc_lock_define_initialized (static, lock);
46 __libc_lock_lock (lock);
48 /* Retest in case some other thread arrived here at the same time. */
49 if (h == NULL)
51 h = __libc_dlopen (LIBCIDN_SO);
53 if (h == NULL)
54 h = (void *) 1l;
55 else
57 /* Get the function we are interested in. */
58 to_ascii_lz = __libc_dlsym (h, "idna_to_ascii_lz");
59 to_unicode_lzlz = __libc_dlsym (h, "idna_to_unicode_lzlz");
60 if (to_ascii_lz == NULL || to_unicode_lzlz == NULL)
62 __libc_dlclose (h);
63 h = (void *) 1l;
68 __libc_lock_unlock (lock);
72 /* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or
73 return IDNA_DLOPEN_ERROR on failure. */
74 int
75 __idna_to_unicode_lzlz (const char *input, char **output, int flags)
77 /* If the input string contains no "xn--" prefix for a component of
78 the name we can pass it up right away. */
79 const char *cp = input;
80 while (*cp != '\0')
82 if (strncmp (cp, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX)) == 0)
83 break;
85 /* On to the next part of the name. */
86 cp = __strchrnul (cp, '.');
87 if (*cp == '.')
88 ++cp;
91 if (*cp == '\0')
93 *output = (char *) input;
94 return IDNA_SUCCESS;
97 if (h == NULL)
98 load_dso ();
100 if (h == (void *) 1l)
101 return IDNA_DLOPEN_ERROR;
103 return to_unicode_lzlz (input, output, flags);
107 /* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or
108 return IDNA_DLOPEN_ERROR on failure. */
110 __idna_to_ascii_lz (const char *input, char **output, int flags)
112 /* If the input string contains no non-ASCII character the output
113 string will be the same. No valid locale encoding does not have
114 this property. */
115 const char *cp = input;
116 while (*cp != '\0' && isascii (*cp))
117 ++cp;
119 if (*cp == '\0')
121 *output = (char *) input;
122 return IDNA_SUCCESS;
125 if (h == NULL)
126 load_dso ();
128 if (h == (void *) 1l)
129 return IDNA_DLOPEN_ERROR;
131 return to_ascii_lz (input, output, flags);
135 #ifndef NOT_IN_libc
136 libc_freeres_fn (unload_libidn)
138 if (h != NULL && h != (void *) 1l)
140 __libc_dlclose (h);
141 h = (void *) 1l;
144 #endif