Allow basic connectivity check via rrsync
[rsync.git] / popt / poptint.c
blobb8dc90f42c296ce94f1af8674e66aa7505f021a5
1 #include "system.h"
2 #include <stdarg.h>
3 #include <errno.h>
4 #ifdef HAVE_LANGINFO_H
5 #include <langinfo.h>
6 #endif
7 #include "poptint.h"
9 /* Any pair of 32 bit hashes can be used. lookup3.c generates pairs, will do. */
10 #define _JLU3_jlu32lpair 1
11 #define jlu32lpair poptJlu32lpair
12 #include "lookup3.c"
14 const char *
15 POPT_prev_char (const char *str)
17 const char *p = str;
19 while (1) {
20 p--;
21 if (((unsigned)*p & 0xc0) != (unsigned)0x80)
22 return p;
26 const char *
27 POPT_next_char (const char *str)
29 const char *p = str;
31 while (*p != '\0') {
32 p++;
33 if (((unsigned)*p & 0xc0) != (unsigned)0x80)
34 break;
36 return p;
39 #if !defined(POPT_fprintf) /* XXX lose all the goop ... */
41 #if defined(ENABLE_NLS) && defined(HAVE_LIBINTL_H) && defined(HAVE_DCGETTEXT)
43 * Rebind a "UTF-8" codeset for popt's internal use.
45 char *
46 POPT_dgettext(const char * dom, const char * str)
48 char * codeset = NULL;
49 char * retval = NULL;
51 if (!dom)
52 dom = textdomain(NULL);
53 codeset = bind_textdomain_codeset(dom, NULL);
54 bind_textdomain_codeset(dom, "UTF-8");
55 retval = dgettext(dom, str);
56 bind_textdomain_codeset(dom, codeset);
58 return retval;
60 #endif
62 #ifdef HAVE_ICONV
63 /**
64 * Return malloc'd string converted from UTF-8 to current locale.
65 * @param istr input string (UTF-8 encoding assumed)
66 * @return localized string
68 static char *
69 strdup_locale_from_utf8 (char * istr)
71 char * codeset = NULL;
72 char * ostr = NULL;
73 iconv_t cd;
75 if (istr == NULL)
76 return NULL;
78 #ifdef HAVE_LANGINFO_H
79 codeset = nl_langinfo ((nl_item)CODESET);
80 #endif
82 if (codeset != NULL && strcmp(codeset, "UTF-8") != 0
83 && (cd = iconv_open(codeset, "UTF-8")) != (iconv_t)-1)
85 char * shift_pin = NULL;
86 size_t db = strlen(istr);
87 char * dstr = malloc((db + 1) * sizeof(*dstr));
88 char * dstr_tmp;
89 char * pin = istr;
90 char * pout = dstr;
91 size_t ib = db;
92 size_t ob = db;
93 size_t err;
95 if (dstr == NULL) {
96 (void) iconv_close(cd);
97 return NULL;
99 err = iconv(cd, NULL, NULL, NULL, NULL);
100 while (1) {
101 *pout = '\0';
102 err = iconv(cd, &pin, &ib, &pout, &ob);
103 if (err != (size_t)-1) {
104 if (shift_pin == NULL) {
105 shift_pin = pin;
106 pin = NULL;
107 ib = 0;
108 continue;
110 } else
111 switch (errno) {
112 case E2BIG:
113 { size_t used = (size_t)(pout - dstr);
114 db *= 2;
115 dstr_tmp = realloc(dstr, (db + 1) * sizeof(*dstr));
116 if (dstr_tmp == NULL) {
117 free(dstr);
118 (void) iconv_close(cd);
119 return NULL;
121 dstr = dstr_tmp;
122 pout = dstr + used;
123 ob = db - used;
124 continue;
125 } break;
126 case EINVAL:
127 case EILSEQ:
128 default:
129 break;
131 break;
133 (void) iconv_close(cd);
134 *pout = '\0';
135 ostr = xstrdup(dstr);
136 free(dstr);
137 } else
138 ostr = xstrdup(istr);
140 return ostr;
142 #endif
145 POPT_fprintf (FILE * stream, const char * format, ...)
147 char * b = NULL, * ob = NULL;
148 int rc;
149 va_list ap;
151 #if defined(HAVE_VASPRINTF)
152 va_start(ap, format);
153 if ((rc = vasprintf(&b, format, ap)) < 0)
154 b = NULL;
155 va_end(ap);
156 #else
157 size_t nb = (size_t)1;
159 /* HACK: add +1 to the realloc no. of bytes "just in case". */
160 /* XXX Likely unneeded, the issues wrto vsnprintf(3) return b0rkage have
161 * to do with whether the final '\0' is counted (or not). The code
162 * below already adds +1 for the (possibly already counted) trailing NUL.
164 while ((b = realloc(b, nb+1)) != NULL) {
165 va_start(ap, format);
166 rc = vsnprintf(b, nb, format, ap);
167 va_end(ap);
168 if (rc > -1) { /* glibc 2.1 */
169 if ((size_t)rc < nb)
170 break;
171 nb = (size_t)(rc + 1); /* precise buffer length known */
172 } else /* glibc 2.0 */
173 nb += (nb < (size_t)100 ? (size_t)100 : nb);
174 ob = b;
176 #endif
178 rc = 0;
179 if (b != NULL) {
180 #ifdef HAVE_ICONV
181 ob = strdup_locale_from_utf8(b);
182 if (ob != NULL) {
183 rc = fprintf(stream, "%s", ob);
184 free(ob);
185 } else
186 #endif
187 rc = fprintf(stream, "%s", b);
188 free (b);
191 return rc;
194 #endif /* !defined(POPT_fprintf) */