summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scp.c2
-rw-r--r--sftp.c2
-rw-r--r--ssh.c3
-rw-r--r--utf8.c42
-rw-r--r--utf8.h1
5 files changed, 47 insertions, 3 deletions
diff --git a/scp.c b/scp.c
index c67cd71df..b4db85198 100644
--- a/scp.c
+++ b/scp.c
@@ -379,7 +379,7 @@ main(int argc, char **argv)
379 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 379 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
380 sanitise_stdfd(); 380 sanitise_stdfd();
381 381
382 setlocale(LC_CTYPE, ""); 382 msetlocale();
383 383
384 /* Copy argv, because we modify it */ 384 /* Copy argv, because we modify it */
385 newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv)); 385 newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv));
diff --git a/sftp.c b/sftp.c
index af6e3a69a..2b8fdabfb 100644
--- a/sftp.c
+++ b/sftp.c
@@ -2272,7 +2272,7 @@ main(int argc, char **argv)
2272 ssh_malloc_init(); /* must be called before any mallocs */ 2272 ssh_malloc_init(); /* must be called before any mallocs */
2273 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 2273 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
2274 sanitise_stdfd(); 2274 sanitise_stdfd();
2275 setlocale(LC_CTYPE, ""); 2275 msetlocale();
2276 2276
2277 __progname = ssh_get_progname(argv[0]); 2277 __progname = ssh_get_progname(argv[0]);
2278 memset(&args, '\0', sizeof(args)); 2278 memset(&args, '\0', sizeof(args));
diff --git a/ssh.c b/ssh.c
index 8aa8daae4..ee0b16dc2 100644
--- a/ssh.c
+++ b/ssh.c
@@ -109,6 +109,7 @@
109#include "version.h" 109#include "version.h"
110#include "ssherr.h" 110#include "ssherr.h"
111#include "myproposal.h" 111#include "myproposal.h"
112#include "utf8.h"
112 113
113#ifdef ENABLE_PKCS11 114#ifdef ENABLE_PKCS11
114#include "ssh-pkcs11.h" 115#include "ssh-pkcs11.h"
@@ -589,7 +590,7 @@ main(int ac, char **av)
589 */ 590 */
590 umask(022); 591 umask(022);
591 592
592 setlocale(LC_CTYPE, ""); 593 msetlocale();
593 594
594 /* 595 /*
595 * Initialize option structure to indicate that no values have been 596 * Initialize option structure to indicate that no values have been
diff --git a/utf8.c b/utf8.c
index f563d3738..87fa9e89a 100644
--- a/utf8.c
+++ b/utf8.c
@@ -27,6 +27,7 @@
27# include <langinfo.h> 27# include <langinfo.h>
28#endif 28#endif
29#include <limits.h> 29#include <limits.h>
30#include <locale.h>
30#include <stdarg.h> 31#include <stdarg.h>
31#include <stdio.h> 32#include <stdio.h>
32#include <stdlib.h> 33#include <stdlib.h>
@@ -288,3 +289,44 @@ mprintf(const char *fmt, ...)
288 va_end(ap); 289 va_end(ap);
289 return ret; 290 return ret;
290} 291}
292
293/*
294 * Set up libc for multibyte output in the user's chosen locale.
295 *
296 * XXX: we are known to have problems with Turkish (i/I confusion) so we
297 * deliberately fall back to the C locale for now. Longer term we should
298 * always prefer to select C.[encoding] if possible, but there's no
299 * standardisation in locales between systems, so we'll need to survey
300 * what's out there first.
301 */
302void
303msetlocale(void)
304{
305 const char *vars[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
306 char *cp;
307 int i;
308
309 /*
310 * We can't yet cope with dotless/dotted I in Turkish locales,
311 * so fall back to the C locale for these.
312 */
313 for (i = 0; vars[i] != NULL; i++) {
314 if ((cp = getenv(vars[i])) == NULL)
315 continue;
316 if (strncasecmp(cp, "TR", 2) != 0)
317 break;
318 /*
319 * If we're in a UTF-8 locale then prefer to use
320 * the C.UTF-8 locale (or equivalent) if it exists.
321 */
322 if ((strcasestr(cp, "UTF-8") != NULL ||
323 strcasestr(cp, "UTF8") != NULL) &&
324 (setlocale(LC_CTYPE, "C.UTF-8") != NULL ||
325 setlocale(LC_CTYPE, "POSIX.UTF-8") != NULL))
326 return;
327 setlocale(LC_CTYPE, "C");
328 return;
329 }
330 /* We can handle this locale */
331 setlocale(LC_CTYPE, "");
332}
diff --git a/utf8.h b/utf8.h
index 43ce1d55d..88c5a34a3 100644
--- a/utf8.h
+++ b/utf8.h
@@ -22,3 +22,4 @@ int fmprintf(FILE *, const char *, ...)
22int vfmprintf(FILE *, const char *, va_list); 22int vfmprintf(FILE *, const char *, va_list);
23int snmprintf(char *, size_t, int *, const char *, ...) 23int snmprintf(char *, size_t, int *, const char *, ...)
24 __attribute__((format(printf, 4, 5))); 24 __attribute__((format(printf, 4, 5)));
25void msetlocale(void);