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