xref: /reactos/sdk/tools/pipetools/piperead.cpp (revision 40462c92)
1 //
2 // piperead.cpp
3 //
4 // Martin Fuchs, 30.11.2003
5 //
6 // Jan Roeloffzen, 26.1.2010
7 // Pipe client, based on msdn example
8 
9 
10 #define WIN32_LEAN_AND_MEAN
11 #include <errno.h>
12 #include <windows.h>
13 #include <stdio.h>
14 
15 #define PIPEREAD_VERSION    "0.3"
16 #define PIPEREAD_NOPIPE     (-101)
17 
18  // This definition currently missing in MinGW.
19 #ifndef FILE_FLAG_FIRST_PIPE_INSTANCE
20 #define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000
21 #endif
22 
23 
24 #define BUFSIZE 1024
25 
26 static void print_error(DWORD win32_error)
27 {
28     fprintf(stderr, "WIN32 error %lu\n", win32_error);
29 }
30 
31 static int pipeServer(char *path)
32 {
33     HANDLE hPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX|FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_WAIT|PIPE_TYPE_BYTE, 1, 4096, 4096, 30000, NULL);
34 
35     if (hPipe == INVALID_HANDLE_VALUE) {
36         print_error(GetLastError());
37         return 1;
38     }
39 
40     for(;;) {
41         DWORD read;
42         BYTE buffer[BUFSIZE];
43 
44         if (!ReadFile(hPipe, buffer, sizeof(buffer), &read, NULL)) {
45             DWORD error = GetLastError();
46 
47             if (error == ERROR_PIPE_LISTENING) {
48                 Sleep(1000);
49             } else if (error == ERROR_BROKEN_PIPE) {
50                 CloseHandle(hPipe);
51 
52                 hPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX|FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_WAIT|PIPE_TYPE_BYTE, 1, 4096, 4096, 30000, NULL);
53 
54                 if (hPipe == INVALID_HANDLE_VALUE) {
55                     fprintf(stderr,"INVALID_HANDLE_VALUE\n");
56                     print_error(GetLastError());
57                     return 1;
58                 }
59             } else {
60                 fprintf(stderr,"error %lu\n",error);
61                 print_error(error);
62                 break;
63             }
64         }
65 
66         if (read)
67             fwrite(buffer, read, 1, stdout);
68     }
69 
70     if (!CloseHandle(hPipe))
71         print_error(GetLastError());
72 
73     return 0;
74 }
75 
76 
77 static int pipeClient(char *path)
78 {
79     HANDLE hPipe=INVALID_HANDLE_VALUE;
80     TCHAR  chBuf[BUFSIZE];
81     BOOL   fSuccess = FALSE;
82     DWORD  cbRead;
83     DWORD  Err;
84     int res = 0;
85 
86     setvbuf(stdout, NULL, _IONBF, 0);
87     while (1) {
88         hPipe = CreateFile(path,           // pipe name
89                            GENERIC_READ,
90                            0,              // no sharing
91                            NULL,           // default security attributes
92                            OPEN_EXISTING,  // opens existing pipe
93                            0,              // default attributes
94                            NULL);          // no template file
95 
96         // Break if the pipe handle is valid.
97         if (hPipe != INVALID_HANDLE_VALUE)
98             break;
99 
100         // Exit if an error other than ERROR_PIPE_BUSY occurs.
101         Err = GetLastError();
102         if (Err != ERROR_PIPE_BUSY) {
103             if (ERROR_FILE_NOT_FOUND == Err)
104             {
105                 res = PIPEREAD_NOPIPE;
106                 return res;
107             }
108             else
109             {
110                 fprintf(stderr,"Could not open pipe %s. Error=%lu\n", path, Err );
111                 res = -1;
112             }
113             break;
114         }
115 
116         // All pipe instances are busy, so wait for 20 seconds.
117         if ( ! WaitNamedPipe(path, 20000)) {
118             fprintf(stderr,"Could not open pipe: 20 second wait timed out.");
119             res = -2;
120             break;
121         }
122     }
123 
124     if (!res) do {
125         fSuccess = ReadFile(hPipe,    // pipe handle
126                             chBuf,    // buffer to receive reply
127                             BUFSIZE,  // size of buffer
128                             &cbRead,  // number of bytes read
129                             NULL);    // not overlapped
130 
131         if ( ! fSuccess ) {
132             Err = GetLastError();
133             if ( Err == ERROR_MORE_DATA ) {
134                 fSuccess = TRUE;
135             } else {
136                 fprintf(stderr, "ReadFile: Error %lu \n", Err );
137                 res = -9;
138                 break;
139             }
140         }
141 
142         fwrite(chBuf,1,cbRead,stdout);
143     } while ( fSuccess);
144 
145     if ( ! fSuccess) {
146         fprintf(stderr, "ReadFile from pipe failed. Error=%lu\n", GetLastError() );
147     }
148 
149     if (hPipe != INVALID_HANDLE_VALUE)
150         CloseHandle(hPipe);
151 
152     return res;
153 
154 }
155 
156 static int fileClient(const char *path)
157 {
158     int res = 0;
159     FILE *fin;
160     int c;
161 
162     setvbuf(stdout, NULL, _IONBF, 0);
163     if (!(fin = fopen(path, "r"))) {
164         fprintf(stderr,"Could not fopen %s (%s)\n", path, strerror(errno) );
165         return -1;
166     }
167 
168     while ((c = fgetc(fin)) != EOF) {
169         fputc(c, stdout);
170     }
171 
172     fclose(fin);
173     return res;
174 }
175 
176 void usage(void)
177 {
178     fprintf(stderr, "piperead " PIPEREAD_VERSION "\n\n");
179     fprintf(stderr, "Usage: piperead [-c] <named pipe>\n");
180     fprintf(stderr, "-c means Client mode\n");
181     fprintf(stderr, "Example: piperead -c \\\\.\\pipe\\kdbg | log2lines -c\n\n");
182 }
183 
184 int main(int argc, char** argv)
185 {
186     char path[MAX_PATH];
187     const char* pipe_name;
188     const char* clientMode;
189     int res = 0;
190 
191     pipe_name = "com_1";
192     clientMode = NULL;
193     switch (argc) {
194     case 3:
195         clientMode = *++argv;
196         if (strcmp(clientMode,"-c") != 0) {
197             fprintf(stderr,"Invalid option: %s\n", clientMode);
198             clientMode = NULL;
199             res = -6;
200         }
201         //fall through
202     case 2:
203         pipe_name = *++argv;
204         if (strcmp(pipe_name,"-h") == 0) {
205             res = -7;
206         }
207         break;
208     default:
209         res = -8;
210         break;
211     }
212     if (res) {
213         usage();
214         return res;
215     }
216 
217     if ( pipe_name[0] == '\\' ) {
218         //assume caller specified full path
219         sprintf(path, "%s", pipe_name);
220     } else {
221         sprintf(path, "\\\\.\\pipe\\%s", pipe_name);
222     }
223 
224     if ( clientMode ) {
225         res = pipeClient(path);
226         if (res == PIPEREAD_NOPIPE) {
227             res = fileClient(pipe_name);
228         }
229     } else {
230         res = pipeServer(path);
231     }
232 
233     return res;
234 }
235