External TEE command.
[reactos.git] / rosapps / cmdutils / tee.c
1 /*
2 * TEE.C - external command.
3 *
4 * clone from 4nt tee command
5 *
6 * 01 Sep 1999 - Dr.F <dfaustus@freemail.it>
7 * started
8 *
9 *
10 */
11
12
13 #include <windows.h>
14 #include <tchar.h>
15 #include <stdio.h>
16 #include <malloc.h>
17
18
19
20 #define TEE_BUFFER_SIZE 8192
21
22 /*these are function that emulate the ones used in cmd*/
23
24 /*many of them are just copied in this file from their
25 original location*/
26
27 VOID ConOutPuts (LPTSTR szText)
28 {
29 DWORD dwWritten;
30
31 WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), szText, _tcslen(szText), &dwWritten, NULL);
32 #if 0
33 WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), "\x0a\x0d", 2, &dwWritten, NULL);
34 #endif
35 WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), "\n", 1, &dwWritten, NULL);
36 }
37
38
39 VOID ConErrPrintf (LPTSTR szFormat, ...)
40 {
41 DWORD dwWritten;
42 TCHAR szOut[4096];
43 va_list arg_ptr;
44
45 va_start (arg_ptr, szFormat);
46 _vstprintf (szOut, szFormat, arg_ptr);
47 va_end (arg_ptr);
48
49 WriteFile (GetStdHandle (STD_ERROR_HANDLE), szOut, _tcslen(szOut), &dwWritten, NULL);
50 }
51
52
53
54 VOID error_sfile_not_found (LPTSTR f)
55 {
56 ConErrPrintf (_T("Error opening file") _T(" - %s\n"), f);
57 }
58
59
60
61
62 VOID ConErrPuts (LPTSTR szText)
63 {
64 ConErrPrintf("%s\n",szText );
65 }
66
67
68 INT main (int argc,char **p)
69 {
70 /*reading/writing buffer*/
71 TCHAR buff[TEE_BUFFER_SIZE];
72
73 /*handle for file and console*/
74 HANDLE hConsoleIn,hConsoleOut;
75
76 /*bytes written by WriteFile and ReadFile*/
77 DWORD dwRead,dwWritten;
78
79
80 BOOL bRet,bAppend=FALSE;
81
82
83 /*command line parsing stuff*/
84 LPTSTR tmp;
85 INT i;
86 BOOL bQuote;
87
88 /*file list implementation*/
89 LPTSTR *files;
90 INT iFileCounter=0;
91 HANDLE *hFile;
92
93 /*used to remove '"' (if any)*/
94 INT add;
95
96 DWORD dw;
97
98
99 if (argc < 2)
100 return 1;
101
102 if (_tcsncmp (p[1], _T("/?"), 2) == 0)
103 {
104 ConOutPuts (_T("Copy standard input to both standard output and a file.\n"
105 "\n"
106 "TEE [/A] file...\n"
107 "\n"
108 " file One or more files that will receive output.\n"
109 " /A Append output to files.\n"));
110 return 0;
111 }
112
113 files = malloc(sizeof(LPTSTR)*argc);
114 hFile = malloc(sizeof(HANDLE)*argc);
115
116 hConsoleIn=GetStdHandle(STD_INPUT_HANDLE);
117 hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE);
118
119 /*parse command line for /a and file name(s)*/
120 for(i=1;i <argc;i++)
121 {
122 bQuote=FALSE;
123 add=0;
124
125 if(_tcsnicmp(p[i],_T("/a"),2) == 0)
126 {
127 bAppend = TRUE;
128 continue;
129 }
130
131 /*remove quote if any*/
132 if (p[i][0] == _T('"'))
133 {
134 tmp = _tcschr (p[i]+1, _T('"'));
135 if (tmp != 0)
136 {
137 add = 1;
138 *tmp= _T('\0');
139 }
140 }
141
142 /*add filename to array of filename*/
143 /*
144 if( iFileCounter >= sizeof(files) / sizeof(*files) )
145 {
146 ConErrPrintf("too many files, maximum is %d\n",sizeof(files) / sizeof(*files));
147 return 1;
148 }
149 */
150
151 files[iFileCounter++]= p[i]+add;
152 }
153
154 /*open file(s)*/
155 for(i=0;i<iFileCounter;i++)
156 {
157 //l=0;
158 hFile[i] = CreateFile(files[i],GENERIC_WRITE,
159 0,NULL,
160 OPEN_ALWAYS,
161 FILE_ATTRIBUTE_NORMAL,NULL);
162
163 if (hFile[i] == INVALID_HANDLE_VALUE)
164 {
165 error_sfile_not_found (files[i]);
166
167 for(i=0;i<iFileCounter;i++)
168 CloseHandle (hFile[i]);
169
170 free (files);
171 free (hFile);
172
173 return 1;
174 }
175
176 /*set append mode*/
177 if (bAppend)
178 {
179 if (GetFileType (hFile[i]) == FILE_TYPE_DISK)
180 {
181 dw = SetFilePointer (hFile[i],0,NULL,FILE_END);
182 if (dw == 0xFFFFFFFF)
183 {
184 ConErrPrintf(_T("error moving to end of file %s"),files[i]);
185
186 for(i=0;i<iFileCounter;i++)
187 CloseHandle (hFile[i]);
188
189 free (files);
190 free (hFile);
191
192 return 1;
193 }
194
195 ConErrPrintf(_T("SetFilePointer() = %d\n"),dw);
196 }
197 }
198 }
199
200 /*read and write*/
201 do
202 {
203 bRet = ReadFile(hConsoleIn,buff,sizeof(buff),&dwRead,NULL);
204
205 if (dwRead>0 && bRet)
206 {
207 for(i=0;i<iFileCounter;i++)
208 WriteFile(hFile[i],buff,dwRead,&dwWritten,NULL);
209
210 WriteFile(hConsoleOut,buff,dwRead,&dwWritten,NULL);
211 }
212 } while(dwRead>0 && bRet);
213
214 for(i=0;i<iFileCounter;i++)
215 CloseHandle (hFile[i]);
216
217 free (files);
218 free (hFile);
219
220 return 0;
221 }
222
223 /* EOF */