fgets and utf8 functions for Windows (#87)
This commit is contained in:
parent
0ed1ef55f7
commit
70da1e67ea
|
@ -283,7 +283,6 @@
|
|||
<ClCompile Include="$(OpenSSH-Src-Path)platform-tracing.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)platform.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)sandbox-pledge.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)utf8.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\ttymodes_windows.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)digest-openssl.c">
|
||||
<ExcludedFromBuild Condition="$(UseOpenSSL)==false">true</ExcludedFromBuild>
|
||||
|
|
|
@ -282,9 +282,6 @@
|
|||
<ClCompile Include="$(OpenSSH-Src-Path)sandbox-pledge.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)utf8.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)contrib\win32\win32compat\ttymodes_windows.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tncon.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32-utf8.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tncon.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\tnnet.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\utf.c" />
|
||||
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\win32-utf8.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
FILE* w32_fopen_utf8(const char *, const char *);
|
||||
#define fopen w32_fopen_utf8
|
||||
|
||||
char* w32_fgets(char *str, int n, FILE *stream);
|
||||
#define fgets w32_fgets
|
||||
|
||||
int w32_setvbuf(FILE *stream,char *buffer, int mode, size_t size);
|
||||
#define setvbuf w32_setvbuf
|
||||
|
||||
/* stdio.h additional definitions */
|
||||
#define popen _popen
|
||||
#define pclose _pclose
|
||||
|
@ -14,4 +20,3 @@ FILE* w32_fdopen(int fd, const char *mode);
|
|||
|
||||
int w32_rename(const char *old_name, const char *new_name);
|
||||
#define rename w32_rename
|
||||
|
||||
|
|
|
@ -276,6 +276,75 @@ w32_fopen_utf8(const char *path, const char *mode)
|
|||
return f;
|
||||
}
|
||||
|
||||
/* fgets to support Unicode input */
|
||||
char*
|
||||
w32_fgets(char *str, int n, FILE *stream) {
|
||||
HANDLE h = (HANDLE)_get_osfhandle(_fileno(stream));
|
||||
wchar_t* str_w = NULL;
|
||||
char *ret = NULL, *str_tmp = NULL;
|
||||
|
||||
if (h != NULL && h != INVALID_HANDLE_VALUE
|
||||
&& GetFileType(h) == FILE_TYPE_CHAR) {
|
||||
/*
|
||||
* read only n/4 wide chars from console
|
||||
* each UTF-16 char may bloat upto 4 utf-8 chars when converted to utf-8
|
||||
* so we can fit in str[n] provided as input
|
||||
*/
|
||||
if ((str_w = malloc((n/4) * sizeof(wchar_t))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
/* prepare for Unicode input */
|
||||
_setmode(_fileno(stream), O_U16TEXT);
|
||||
if (fgetws(str_w, n/4, stream) == NULL)
|
||||
goto cleanup;
|
||||
if ((str_tmp = utf16_to_utf8(str_w)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
if (strlen(str_tmp) > n - 1) {
|
||||
/* shouldn't happen. but handling in case */
|
||||
errno = EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
memcpy(str, str_tmp, strlen(str_tmp) + 1);
|
||||
ret = str;
|
||||
}
|
||||
else
|
||||
ret = fgets(str, n, stream);
|
||||
cleanup:
|
||||
if (str_w)
|
||||
free(str_w);
|
||||
if (str_tmp)
|
||||
free(str_tmp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Account for differences between Unix's and Windows versions of setvbuf */
|
||||
int
|
||||
w32_setvbuf(FILE *stream, char *buffer, int mode, size_t size) {
|
||||
|
||||
/* BUG: setvbuf on console stream interferes with Unicode I/O */
|
||||
HANDLE h = (HANDLE)_get_osfhandle(_fileno(stream));
|
||||
|
||||
if (h != NULL && h != INVALID_HANDLE_VALUE
|
||||
&& GetFileType(h) == FILE_TYPE_CHAR)
|
||||
return 0;
|
||||
|
||||
/* BUG: setvbuf on file stream is interfering with w32_fopen */
|
||||
/* short circuit for now*/
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* if size is 0, set no buffering.
|
||||
* Windows does not differentiate __IOLBF and _IOFBF
|
||||
*/
|
||||
if (size == 0)
|
||||
return setvbuf(stream, NULL, _IONBF, 0);
|
||||
else
|
||||
return setvbuf(stream, buffer, mode, size);
|
||||
}
|
||||
|
||||
char *
|
||||
w32_programdir()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Temporary Windows versions of functions implemented in utf8.c
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int
|
||||
vfmprintf(FILE *f, const char *fmt, va_list list)
|
||||
{
|
||||
return vfprintf(f, fmt, list);
|
||||
}
|
||||
|
||||
int
|
||||
mprintf(const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list valist;
|
||||
va_start(valist, fmt);
|
||||
ret = vfmprintf(stdout, fmt, valist);
|
||||
va_end(valist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
fmprintf(FILE *f, const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
va_list valist;
|
||||
va_start(valist, fmt);
|
||||
ret = vfmprintf(f, fmt, valist);
|
||||
va_end(valist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
snmprintf(char *buf, size_t len, int *written, const char *fmt, ...)
|
||||
{
|
||||
int num;
|
||||
va_list valist;
|
||||
va_start(valist, fmt);
|
||||
num = vsnprintf(buf, len, fmt, valist);
|
||||
va_end(valist);
|
||||
*written = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
msetlocale(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
20
scp.c
20
scp.c
|
@ -1034,17 +1034,7 @@ rsource(char *name, struct stat *statp)
|
|||
(void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
|
||||
(u_int) (statp->st_mode & FILEMODEMASK), 0, last);
|
||||
if (verbose_mode)
|
||||
#ifdef WINDOWS
|
||||
/* TODO - make fmprintf work for Windows */
|
||||
{
|
||||
printf("Entering directory: ");
|
||||
wchar_t* wtmp = utf8_to_utf16(path);
|
||||
WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0);
|
||||
free(wtmp);
|
||||
}
|
||||
#else /* !WINDOWS */
|
||||
fmprintf(stderr, "Entering directory: %s", path);
|
||||
#endif /* !WINDOWS */
|
||||
(void) atomicio(vwrite, remout, path, strlen(path));
|
||||
if (response() < 0) {
|
||||
closedir(dirp);
|
||||
|
@ -1119,17 +1109,7 @@ sink(int argc, char **argv)
|
|||
} while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
|
||||
*cp = 0;
|
||||
if (verbose_mode)
|
||||
#ifdef WINDOWS
|
||||
/* TODO - make fmprintf work for Windows */
|
||||
{
|
||||
printf("Sink: ");
|
||||
wchar_t* wtmp = utf8_to_utf16(buf);
|
||||
WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wtmp, wcslen(wtmp), 0, 0);
|
||||
free(wtmp);
|
||||
}
|
||||
#else /* !WINDOWS */
|
||||
fmprintf(stderr, "Sink: %s", buf);
|
||||
#endif /* !WINDOWS */
|
||||
|
||||
if (buf[0] == '\01' || buf[0] == '\02') {
|
||||
if (iamremote == 0) {
|
||||
|
|
87
sftp.c
87
sftp.c
|
@ -292,27 +292,6 @@ help(void)
|
|||
"? Synonym for help\n");
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
/* printf version to account for utf-8 input */
|
||||
/* TODO - merge this with vfmprint */
|
||||
static void printf_utf8(char *fmt, ... ) {
|
||||
/* TODO - is 1024 sufficient */
|
||||
char buf[1024];
|
||||
int length = 0;
|
||||
|
||||
va_list valist;
|
||||
va_start(valist, fmt);
|
||||
length = vsnprintf(buf, 1024, fmt, valist);
|
||||
va_end(valist);
|
||||
|
||||
write(STDOUT_FILENO, buf, length);
|
||||
}
|
||||
|
||||
/* override mprintf */
|
||||
#define mprintf(a,...) printf_utf8((a), __VA_ARGS__)
|
||||
#define printf(a,...) printf_utf8((a), __VA_ARGS__)
|
||||
#endif /* WINDOWS */
|
||||
|
||||
static void
|
||||
local_do_shell(const char *args)
|
||||
{
|
||||
|
@ -420,7 +399,7 @@ make_absolute(char *p, const char *pwd)
|
|||
p = abs_str;
|
||||
}
|
||||
|
||||
/* convert '\\' tp '/' */
|
||||
/* convert '\\' to '/' */
|
||||
convertToForwardslash(p);
|
||||
|
||||
/* Append "/" if needed to the absolute windows path */
|
||||
|
@ -925,23 +904,7 @@ do_ls_dir(struct sftp_conn *conn, const char *path,
|
|||
} else
|
||||
mprintf("%s\n", d[n]->longname);
|
||||
} else {
|
||||
#ifdef WINDOWS
|
||||
/* cannot use printf_utf8 becuase of width specification */
|
||||
/* printf_utf8 does not account for utf-16 based argument widths */
|
||||
char *p = NULL;
|
||||
wchar_t buf[1024];
|
||||
wchar_t* wtmp = utf8_to_utf16(fname);
|
||||
swprintf(buf, 1024, L"%-*s", colspace, wtmp);
|
||||
|
||||
if ((p = utf16_to_utf8(buf)) == NULL)
|
||||
continue;
|
||||
|
||||
write(STDOUT_FILENO, p, strlen(p));
|
||||
free(wtmp);
|
||||
free(p);
|
||||
#else
|
||||
mprintf("%-*s", colspace, fname);
|
||||
#endif
|
||||
if (c >= columns) {
|
||||
printf("\n");
|
||||
c = 1;
|
||||
|
@ -1025,23 +988,7 @@ do_globbed_ls(struct sftp_conn *conn, const char *path,
|
|||
mprintf("%s\n", lname);
|
||||
free(lname);
|
||||
} else {
|
||||
#ifdef WINDOWS
|
||||
/* cannot use printf_utf8 becuase of width specification */
|
||||
/* printf_utf8 does not account for utf-16 based argument widths */
|
||||
char *p = NULL;
|
||||
wchar_t buf[1024];
|
||||
wchar_t* wtmp = utf8_to_utf16(fname);
|
||||
swprintf(buf, 1024, L"%-*s", colspace, wtmp);
|
||||
|
||||
if ((p = utf16_to_utf8(buf)) == NULL)
|
||||
continue;
|
||||
|
||||
write(STDOUT_FILENO, p, strlen(p));
|
||||
free(wtmp);
|
||||
free(p);
|
||||
#else
|
||||
mprintf("%-*s", colspace, fname);
|
||||
#endif
|
||||
if (c >= columns) {
|
||||
printf("\n");
|
||||
c = 1;
|
||||
|
@ -2211,20 +2158,8 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
|
|||
interactive = !batchmode && isatty(STDIN_FILENO);
|
||||
err = 0;
|
||||
|
||||
#ifdef WINDOWS
|
||||
/* Min buffer size allowed in Windows is 2*/
|
||||
setvbuf(stdout, NULL, _IOLBF, 2);
|
||||
|
||||
/* We do this only in interactive mode as we are unable to read files with UTF8 BOM */
|
||||
if (interactive) {
|
||||
setvbuf(infile, NULL, _IOLBF, 2);
|
||||
_setmode(_fileno(stdin), O_U16TEXT); /* prepare for Unicode input */
|
||||
}
|
||||
#else /* !WINDOWS */
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
setvbuf(infile, NULL, _IOLBF, 0);
|
||||
#endif /* !WINDOWS */
|
||||
|
||||
|
||||
for (;;) {
|
||||
char *cp;
|
||||
|
@ -2232,25 +2167,6 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
|
|||
signal(SIGINT, SIG_IGN);
|
||||
|
||||
if (el == NULL) {
|
||||
#ifdef WINDOWS
|
||||
/* fgets on Windows does not support Unicode input*/
|
||||
if (interactive) {
|
||||
wchar_t wcmd[2048];
|
||||
printf("sftp> ");
|
||||
if (fgetws(wcmd, sizeof(cmd)/sizeof(wchar_t), infile) == NULL) {
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
else {
|
||||
char *pcmd = NULL;
|
||||
if ((pcmd = utf16_to_utf8(wcmd)) == NULL)
|
||||
fatal("failed to convert input arguments");
|
||||
strcpy(cmd, pcmd);
|
||||
free(pcmd);
|
||||
}
|
||||
} else if (fgets(cmd, sizeof(cmd), infile) == NULL)
|
||||
break;
|
||||
#else /* !WINDOWS */
|
||||
if (interactive)
|
||||
printf("sftp> ");
|
||||
if (fgets(cmd, sizeof(cmd), infile) == NULL) {
|
||||
|
@ -2258,7 +2174,6 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
|
|||
printf("\n");
|
||||
break;
|
||||
}
|
||||
#endif/* !WINDOWS */
|
||||
if (!interactive) { /* Echo command */
|
||||
mprintf("sftp> %s", cmd);
|
||||
if (strlen(cmd) > 0 &&
|
||||
|
|
12
utf8.c
12
utf8.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: utf8.c,v 1.4 2017/02/02 10:54:25 jsg Exp $ */
|
||||
/* $OpenBSD: utf8.c,v 1.5 2017/02/19 00:10:57 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
|
||||
*
|
||||
|
@ -57,16 +57,11 @@ static int vasnmprintf(char **, size_t, int *, const char *, va_list);
|
|||
|
||||
static int
|
||||
dangerous_locale(void) {
|
||||
#ifdef WINDOWS
|
||||
wchar_t loc[LOCALE_NAME_MAX_LENGTH];
|
||||
GetSystemDefaultLocaleName(loc, LOCALE_NAME_MAX_LENGTH);
|
||||
return wcscmp(loc, L"US-ASCII") && wcscmp(loc, L"UTF-8");
|
||||
#else /* !WINDOWS */
|
||||
char *loc;
|
||||
|
||||
loc = nl_langinfo(CODESET);
|
||||
return strcmp(loc, "US-ASCII") && strcmp(loc, "UTF-8");
|
||||
#endif /* !WINDOWS */
|
||||
return strcmp(loc, "US-ASCII") != 0 && strcmp(loc, "UTF-8") != 0 &&
|
||||
strcmp(loc, "ANSI_X3.4-1968") != 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -337,3 +332,4 @@ msetlocale(void)
|
|||
/* We can handle this locale */
|
||||
setlocale(LC_CTYPE, "");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue