1919#include <Windows.h>
2020#include <ShellAPI.h>
2121
22- #define BUFFSIZE 4096U
23-
2422#define HANDLE_WRITE_ERROR (OFFSET ) do \
2523{ \
26- print (hStdErr, "[tee] Error: Not all data could be written!\n\n"); \
24+ write_text (hStdErr, L "[tee] Error: Not all data could be written!\n\n"); \
2725 OFFSET = MAXDWORD; \
2826} \
2927while (0)
@@ -51,6 +49,8 @@ while (0)
5149} \
5250while (0)
5351
52+ #define BUFFSIZE 4096U
53+
5454static volatile BOOL g_stopping = FALSE;
5555
5656static BOOL WINAPI console_handler (const DWORD ctrlType )
@@ -60,18 +60,50 @@ static BOOL WINAPI console_handler(const DWORD ctrlType)
6060 case CTRL_C_EVENT :
6161 case CTRL_BREAK_EVENT :
6262 case CTRL_CLOSE_EVENT :
63- MessageBoxW (NULL , L"CTRL_C_EVENT" , NULL , MB_TOPMOST );
6463 g_stopping = TRUE;
6564 return TRUE;
6665 default :
6766 return FALSE;
6867 }
6968}
7069
71- static void print (const HANDLE handle , const char * const text )
70+ static char * utf16_to_utf8 (const wchar_t * const input )
71+ {
72+ const int buff_size = WideCharToMultiByte (CP_UTF8 , 0 , input , -1 , NULL , 0 , NULL , NULL );
73+ if (buff_size > 0 )
74+ {
75+ char * const buffer = (char * )LocalAlloc (LPTR , buff_size );
76+ if (buffer )
77+ {
78+ const int result = WideCharToMultiByte (CP_UTF8 , 0 , input , -1 , buffer , buff_size , NULL , NULL );
79+ if ((result > 0 ) && (result <= buff_size ))
80+ {
81+ return buffer ;
82+ }
83+ LocalFree (buffer );
84+ }
85+ }
86+ return NULL ;
87+ }
88+
89+ static BOOL write_text (const HANDLE handle , const wchar_t * const text )
7290{
91+ BOOL result = FALSE;
7392 DWORD written ;
74- WriteFile (handle , text , lstrlenA (text ), & written , NULL );
93+ if (GetConsoleMode (handle , & written ))
94+ {
95+ result = WriteConsoleW (handle , text , lstrlenW (text ), & written , NULL );
96+ }
97+ else
98+ {
99+ char * const utf8_text = utf16_to_utf8 (text );
100+ if (utf8_text )
101+ {
102+ result = WriteFile (handle , utf8_text , lstrlenA (utf8_text ), & written , NULL );
103+ LocalFree (utf8_text );
104+ }
105+ }
106+ return result ;
75107}
76108
77109int wmain (const int argc , const wchar_t * const argv [])
@@ -86,13 +118,13 @@ int wmain(const int argc, const wchar_t *const argv[])
86118
87119 if ((argc < 2 ) || (lstrcmpiW (argv [1 ], L"/?" ) == 0 ) || (lstrcmpiW (argv [1 ], L"--help" ) == 0 ))
88120 {
89- print (hStdErr , "tee for Windows [" __DATE__ "]\n\n" );
90- print (hStdErr , "Usage:\n" );
91- print (hStdErr , " your_program.exe [options] | tee.exe [--append] <output_file>\n\n" );
121+ write_text (hStdErr , L "tee for Windows [" TEXT ( __DATE__ ) L "]\n\n" );
122+ write_text (hStdErr , L "Usage:\n" );
123+ write_text (hStdErr , L " your_program.exe [options] | tee.exe [--append] [--flush ] <output_file>\n\n" );
92124 return 1 ;
93125 }
94126
95- BOOL append = FALSE;
127+ BOOL append = FALSE, flush = FALSE ;
96128 int argOff = 1 ;
97129
98130 while (argOff < argc )
@@ -108,28 +140,34 @@ int wmain(const int argc, const wchar_t *const argv[])
108140 {
109141 append = TRUE;
110142 }
143+ else if (lstrcmpiW (option , L"flush" ) == 0 )
144+ {
145+ flush = TRUE;
146+ }
111147 else
112148 {
113- print (hStdErr , "[tee] Error: Invalid option encountered!\n\n" );
149+ write_text (hStdErr , L"[tee] Error: Invalid option \"--" );
150+ write_text (hStdErr , option );
151+ write_text (hStdErr , L"\" encountered!\n\n" );
114152 return 1 ;
115153 }
116154 }
117155 else
118156 {
119- break ;
157+ break ; /*stop option processing*/
120158 }
121159 }
122160
123161 if (argOff >= argc )
124162 {
125- print (hStdErr , "[tee] Error: Output file name is missing!\n\n" );
163+ write_text (hStdErr , L "[tee] Error: Output file name is missing!\n\n" );
126164 return 1 ;
127165 }
128166
129167 const HANDLE hFile = CreateFileW (argv [argOff ], GENERIC_WRITE , FILE_SHARE_READ , NULL , append ? OPEN_ALWAYS : CREATE_ALWAYS , 0U , NULL );
130168 if (hFile == INVALID_HANDLE_VALUE )
131169 {
132- print (hStdErr , "[tee] Error: Failed to open the output file for writing!\n\n" );
170+ write_text (hStdErr , L "[tee] Error: Failed to open the output file for writing!\n\n" );
133171 return -1 ;
134172 }
135173
@@ -138,7 +176,7 @@ int wmain(const int argc, const wchar_t *const argv[])
138176 LARGE_INTEGER offset = { .QuadPart = 0LL };
139177 if (!SetFilePointerEx (hFile , offset , NULL , FILE_END ))
140178 {
141- print (hStdErr , "[tee] Error: Failed to move the file pointer to the end of the file!\n\n" );
179+ write_text (hStdErr , L "[tee] Error: Failed to move the file pointer to the end of the file!\n\n" );
142180 CloseHandle (hFile );
143181 return -1 ;
144182 }
@@ -160,12 +198,18 @@ int wmain(const int argc, const wchar_t *const argv[])
160198 {
161199 WRITE_DATA (hStdOut , offsetStdOut );
162200 WRITE_DATA (hFile , offsetFile );
201+ if (flush )
202+ {
203+ FlushFileBuffers (hFile );
204+ }
163205 }
164206 }
165207
166208cleanup :
167209
210+ FlushFileBuffers (hFile );
168211 CloseHandle (hFile );
212+
169213 return 0 ;
170214}
171215
0 commit comments