From 94dd465e7bc437a0e70beb3a8647df96772d16de Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Mon, 11 Sep 2023 09:41:54 -0500 Subject: [PATCH] Change mstpcap to either write to pipe or file, not both. (#492) * Change mstpcap to either write to pipe or file, not both. Fixed bug#83 of mstpcap.exe Permission Denied in Wireshark --------- Co-authored-by: Steve Karg --- CHANGELOG.md | 53 +++---- apps/mstpcap/main.c | 370 +++++++++++++++++++++++--------------------- 2 files changed, 217 insertions(+), 206 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a44947a2..ba0e3b3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # BACnet Stack ChangeLog -BACnet open source protocol stack C library for embedded systems, +BACnet open source protocol stack C library for embedded systems, Linux, MacOS, BSD, and Windows All notable changes to this project will be documented in this file. @@ -16,16 +16,16 @@ The git repositories are hosted at the following sites: ### Security -- Added or updated secure the BACnet primitive value decoders -named bacnet_x_decode(), bacnet_x_application_decode() and -bacnet_x_context_decode where x is one of the 13 BACnet primitive value names. -The updated API includes an APDU size to prevent over-reading of an APDU buffer. +- Added or updated secure the BACnet primitive value decoders +named bacnet_x_decode(), bacnet_x_application_decode() and +bacnet_x_context_decode where x is one of the 13 BACnet primitive value names. +The updated API includes an APDU size to prevent over-reading of an APDU buffer. Improved or added unit test code coverage for the primitive value decoders (#481) -- marked the insecure decoding API as 'deprecated' which is defined in +- marked the insecure decoding API as 'deprecated' which is defined in src/bacnet/basic/sys/platform.h and can be disabled during a build. (#481) -- secured decoders for BACnetTimeValue, BACnetHostNPort, BACnetTimeStamp, +- secured decoders for BACnetTimeValue, BACnetHostNPort, BACnetTimeStamp, BACnetAddress, and Weekly_Schedule and improved unit test code coverage. (#481) -- secured AtomicReadFile and AtomicWriteFile service decoders and +- secured AtomicReadFile and AtomicWriteFile service decoders and improved unit test code coverage. (#481) - secured BACnet Error service decoder and improved unit test code coverage. (#481) - improved test code coverage for BACnet objects and properties. (#481) @@ -42,6 +42,7 @@ improved unit test code coverage. (#481) Link_Speed property is writable (#488) - Fixed Microchip xmega xplained example project to build under GCC in pipeline. - Fixed BACnet/IP on OS to bind broadcast to specific port (#489) +- Fixed (bug#83) mstpcap.exe permission denied in Wireshark (#492) ## [1.1.2] - 2023-08-18 @@ -87,7 +88,7 @@ Link_Speed property is writable (#488) - Added minimim support for BACnet protocol-revision 0 through 24. See  BACNET_PROTOCOL_REVISION define in bacdef.h -- Added example objects for color and color temperature, new for protocol-revision 24. +- Added example objects for color and color temperature, new for protocol-revision 24. - Added current-command-priority to output objects revision 17 or later. - Added demo apps ack-alarm, add-list-element, and event (#418) - Added UTC option to BACnet TimeSync app (#396) @@ -95,7 +96,7 @@ BACNET_PROTOCOL_REVISION define in bacdef.h - Added --retry option for repeating Who-Is or I-Am C number of times (#199) - Added write BDT application (#170) - Added repeat option to Who-Is and I-Am app (#117) -- Added UTF8 multibyte to wide char printing in ReadProperty and ReadPropertyMultiple +- Added UTF8 multibyte to wide char printing in ReadProperty and ReadPropertyMultiple apps if supported by the compiler and C library (#106). - Added IPv6 Foreign Device Registration and IPv6 support for BSD and macOS for apps - Added example of spawning 100 servers using a BBMD connection. @@ -106,23 +107,23 @@ apps if supported by the compiler and C library (#106). ### Changed -- Modified example objects to support CreateObject and DeleteObject API for -these objects: file, analog output, binary output, multi-state output, color, -color temperature). -- Unit tests and functional tests have been moved from the source C files -into their own test files under the test folder in a src/ mirrored folder -structure under test/.  -- The testing framework was moved from ctest to ztest, using CMake, CTest, and LCOV.  -It's now possible to visually view code coverage from the testing of each file -in the library. The tests are run in continuous integration.  Adding new tests -can be done by as copying an existing folder under test/ as a starting point, and -adding the new test folder name into the CMakeLists.txt under test/ folder, or +- Modified example objects to support CreateObject and DeleteObject API for +these objects: file, analog output, binary output, multi-state output, color, +color temperature). +- Unit tests and functional tests have been moved from the source C files +into their own test files under the test folder in a src/ mirrored folder +structure under test/.  +- The testing framework was moved from ctest to ztest, using CMake, CTest, and LCOV.  +It's now possible to visually view code coverage from the testing of each file +in the library. The tests are run in continuous integration.  Adding new tests +can be done by as copying an existing folder under test/ as a starting point, and +adding the new test folder name into the CMakeLists.txt under test/ folder, or editing the existing test C file and extending or fixing the existing test.  -- Most (all?) of the primitive value encoders are now using a snprintf() -style API pattern, where passing NULL in the buffer parameter will -return the length that the buffer would use (i.e. returns the length that the -buffer needs to be).  This makes simple to write the parent encoders to check -the length versus their buffer before attempting the encoding at the expense of +- Most (all?) of the primitive value encoders are now using a snprintf() +style API pattern, where passing NULL in the buffer parameter will +return the length that the buffer would use (i.e. returns the length that the +buffer needs to be).  This makes simple to write the parent encoders to check +the length versus their buffer before attempting the encoding at the expense of an extra function call to get the length. - BACnetARRAY property types now have a helper function to use for encoding (see bacnet_array_encode)  diff --git a/apps/mstpcap/main.c b/apps/mstpcap/main.c index 8d127cd3..1f2008f6 100644 --- a/apps/mstpcap/main.c +++ b/apps/mstpcap/main.c @@ -386,6 +386,7 @@ static void packet_statistics_print(void) fprintf(stdout, "Node Count: %u\n", node_count); fprintf(stdout, "Invalid Frame Count: %lu\n", (long unsigned int)Invalid_Frame_Count); + fflush(stdout); } static void packet_statistics_clear(void) @@ -438,20 +439,20 @@ uint16_t MSTP_Get_Reply( } static char Capture_Filename[64] = "mstp_20090123091200.cap"; -static FILE *pFile = NULL; /* stream pointer */ +static FILE *File_Handle = NULL; /* stream pointer */ #if defined(_WIN32) -static HANDLE hPipe = INVALID_HANDLE_VALUE; /* pipe handle */ +static HANDLE Pipe_Handle = INVALID_HANDLE_VALUE; /* pipe handle */ static void named_pipe_create(char *pipe_name) { if (!Wireshark_Capture) { fprintf(stdout, "mstpcap: Creating Named Pipe \"%s\"\n", pipe_name); } /* create the pipe */ - while (hPipe == INVALID_HANDLE_VALUE) { + while (Pipe_Handle == INVALID_HANDLE_VALUE) { /* use CreateFile rather than CreateNamedPipe */ - hPipe = CreateFile(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, + Pipe_Handle = CreateFile(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (hPipe != INVALID_HANDLE_VALUE) { + if (Pipe_Handle != INVALID_HANDLE_VALUE) { break; } /* if an error occured at handle creation */ @@ -463,36 +464,48 @@ static void named_pipe_create(char *pipe_name) return; } } - ConnectNamedPipe(hPipe, NULL); + ConnectNamedPipe(Pipe_Handle, NULL); } static size_t data_write(const void *ptr, size_t size, size_t nitems) { + size_t written = 0; DWORD cbWritten = 0; - if (hPipe != INVALID_HANDLE_VALUE) { - (void)WriteFile(hPipe, /* handle to pipe */ + + if (Pipe_Handle != INVALID_HANDLE_VALUE) { + (void)WriteFile(Pipe_Handle, /* handle to pipe */ ptr, /* buffer to write from */ size * nitems, /* number of bytes to write */ &cbWritten, /* number of bytes written */ NULL); /* not overlapped I/O */ + written = cbWritten; } - return fwrite(ptr, size, nitems, pFile); + if (File_Handle) { + written = fwrite(ptr, size, nitems, File_Handle); + } + + return written; } static size_t data_write_header( - const void *ptr, size_t size, size_t nitems, bool pipe_enable) + const void *ptr, size_t size, size_t nitems) { + size_t written = 0; DWORD cbWritten = 0; - if (pipe_enable && (hPipe != INVALID_HANDLE_VALUE)) { - (void)WriteFile(hPipe, /* handle to pipe */ + if (Pipe_Handle != INVALID_HANDLE_VALUE) { + (void)WriteFile(Pipe_Handle, /* handle to pipe */ ptr, /* buffer to write from */ size * nitems, /* number of bytes to write */ &cbWritten, /* number of bytes written */ NULL); /* not overlapped I/O */ + written = cbWritten; + } + if (File_Handle) { + written = fwrite(ptr, size, nitems, File_Handle); } - return fwrite(ptr, size, nitems, pFile); + return written; } #else static int FD_Pipe = -1; @@ -513,43 +526,64 @@ static void named_pipe_create(char *name) static size_t data_write(const void *ptr, size_t size, size_t nitems) { - ssize_t bytes = 0; + ssize_t written = 0; + if (FD_Pipe != -1) { - bytes = write(FD_Pipe, ptr, size * nitems); - (void)bytes; + written = write(FD_Pipe, ptr, size * nitems); } - return fwrite(ptr, size, nitems, pFile); + if (File_Handle) { + written = fwrite(ptr, size, nitems, File_Handle); + } + + return written; } static size_t data_write_header( - const void *ptr, size_t size, size_t nitems, bool pipe_enable) + const void *ptr, size_t size, size_t nitems) { - ssize_t bytes = 0; - if (pipe_enable && (FD_Pipe != -1)) { - bytes = write(FD_Pipe, ptr, size * nitems); - (void)bytes; + ssize_t written = 0; + + if (FD_Pipe != -1) { + written = write(FD_Pipe, ptr, size * nitems); } - return fwrite(ptr, size, nitems, pFile); + if (File_Handle) { + written = fwrite(ptr, size, nitems, File_Handle); + } + + return written; } #endif -static void filename_create(char *filename) +static void filename_create_new(void) { BACNET_DATE bdate; BACNET_TIME btime; + char *filename = &Capture_Filename[0]; + size_t filename_size = sizeof(Capture_Filename); - if (filename) { - datetime_local(&bdate, &btime, NULL, NULL); - sprintf(filename, "mstp_%04d%02d%02d%02d%02d%02d.cap", (int)bdate.year, - (int)bdate.month, (int)bdate.day, (int)btime.hour, (int)btime.min, - (int)btime.sec); + if (Wireshark_Capture) { + return; + } + if (File_Handle) { + fclose(File_Handle); + } + File_Handle = NULL; + datetime_local(&bdate, &btime, NULL, NULL); + snprintf(filename, filename_size, "mstp_%04d%02d%02d%02d%02d%02d.cap", + (int)bdate.year, (int)bdate.month, (int)bdate.day, (int)btime.hour, + (int)btime.min, (int)btime.sec); + File_Handle = fopen(filename, "wb"); + if (File_Handle) { + fprintf(stdout, "mstpcap: saving capture to %s\n", filename); + } else { + fprintf(stderr, "mstpcap: failed to open %s: %s\n", filename, + strerror(errno)); } } /* write packet to file in libpcap format */ -static void write_global_header(const char *filename) +static void write_global_header(void) { - static bool pipe_enable = true; /* don't write more than one header */ uint32_t magic_number = 0xa1b2c3d4; /* magic number */ uint16_t version_major = 2; /* major version number */ uint16_t version_minor = 4; /* minor version number */ @@ -559,29 +593,17 @@ static void write_global_header(const char *filename) uint32_t network = DLT_BACNET_MS_TP; /* data link type - BACNET_MS_TP */ /* create a new file. */ - pFile = fopen(filename, "wb"); - if (pFile) { - (void)data_write_header( - &magic_number, sizeof(magic_number), 1, pipe_enable); - (void)data_write_header( - &version_major, sizeof(version_major), 1, pipe_enable); - (void)data_write_header( - &version_minor, sizeof(version_minor), 1, pipe_enable); - (void)data_write_header(&thiszone, sizeof(thiszone), 1, pipe_enable); - (void)data_write_header(&sigfigs, sizeof(sigfigs), 1, pipe_enable); - (void)data_write_header(&snaplen, sizeof(snaplen), 1, pipe_enable); - (void)data_write_header(&network, sizeof(network), 1, pipe_enable); - fflush(pFile); - if (!Wireshark_Capture) { - fprintf(stdout, "mstpcap: saving capture to %s\n", filename); - } - } else { - fprintf(stderr, "mstpcap[header]: failed to open %s: %s\n", filename, - strerror(errno)); - } - if (pipe_enable) { - pipe_enable = false; - } + (void)data_write_header( + &magic_number, sizeof(magic_number), 1); + (void)data_write_header( + &version_major, sizeof(version_major), 1); + (void)data_write_header( + &version_minor, sizeof(version_minor), 1); + (void)data_write_header(&thiszone, sizeof(thiszone), 1); + (void)data_write_header(&sigfigs, sizeof(sigfigs), 1); + (void)data_write_header(&snaplen, sizeof(snaplen), 1); + (void)data_write_header(&network, sizeof(network), 1); + fflush(File_Handle); } static void write_received_packet( @@ -596,66 +618,61 @@ static void write_received_packet( struct timeval tv; size_t max_data = 0; - if (pFile) { - gettimeofday(&tv, NULL); - ts_sec = tv.tv_sec; - ts_usec = tv.tv_usec; - if ((mstp_port->ReceivedValidFrame) || - (mstp_port->ReceivedValidFrameNotForUs)) { - packet_statistics(&tv, mstp_port); - } - (void)data_write(&ts_sec, sizeof(ts_sec), 1); - (void)data_write(&ts_usec, sizeof(ts_usec), 1); - if (mstp_port->ReceivedInvalidFrame) { - if (mstp_port->Index) { - max_data = min(mstp_port->InputBufferSize, mstp_port->Index); - if ((mstp_port->DataLength > 0) && - (mstp_port->Index == (mstp_port->DataLength + 1))) { - /* case where index is not incremented for CRC2, - so only 1 for checksum */ - data_crc_len = 1; - } - incl_len = orig_len = header_len + max_data + data_crc_len; - } else { - /* header only */ - incl_len = orig_len = header_len; + gettimeofday(&tv, NULL); + ts_sec = tv.tv_sec; + ts_usec = tv.tv_usec; + if ((mstp_port->ReceivedValidFrame) || + (mstp_port->ReceivedValidFrameNotForUs)) { + packet_statistics(&tv, mstp_port); + } + (void)data_write(&ts_sec, sizeof(ts_sec), 1); + (void)data_write(&ts_usec, sizeof(ts_usec), 1); + if (mstp_port->ReceivedInvalidFrame) { + if (mstp_port->Index) { + max_data = min(mstp_port->InputBufferSize, mstp_port->Index); + if ((mstp_port->DataLength > 0) && + (mstp_port->Index == (mstp_port->DataLength + 1))) { + /* case where index is not incremented for CRC2, + so only 1 for checksum */ + data_crc_len = 1; } + incl_len = orig_len = header_len + max_data + data_crc_len; } else { - if (mstp_port->DataLength) { - max_data = - min(mstp_port->InputBufferSize, mstp_port->DataLength); - incl_len = orig_len = header_len + max_data + data_crc_len; - } else { - /* header only - or at least some bytes of the header */ - incl_len = orig_len = header_len; - } - } - (void)data_write(&incl_len, sizeof(incl_len), 1); - (void)data_write(&orig_len, sizeof(orig_len), 1); - if (header_len == 1) { - header[0] = mstp_port->DataRegister; - } else if (header_len == 2) { - header[0] = 0x55; - header[1] = mstp_port->DataRegister; - } else { - header[0] = 0x55; - header[1] = 0xFF; - header[2] = mstp_port->FrameType; - header[3] = mstp_port->DestinationAddress; - header[4] = mstp_port->SourceAddress; - header[5] = HI_BYTE(mstp_port->DataLength); - header[6] = LO_BYTE(mstp_port->DataLength); - header[7] = mstp_port->HeaderCRCActual; - } - (void)data_write(header, header_len, 1); - if (max_data) { - (void)data_write(mstp_port->InputBuffer, max_data, 1); - (void)data_write((char *)&mstp_port->DataCRCActualMSB, 1, 1); - (void)data_write((char *)&mstp_port->DataCRCActualLSB, 1, 1); + /* header only */ + incl_len = orig_len = header_len; } } else { - fprintf(stderr, "mstpcap[packet]: failed to open %s: %s\n", - Capture_Filename, strerror(errno)); + if (mstp_port->DataLength) { + max_data = + min(mstp_port->InputBufferSize, mstp_port->DataLength); + incl_len = orig_len = header_len + max_data + data_crc_len; + } else { + /* header only - or at least some bytes of the header */ + incl_len = orig_len = header_len; + } + } + (void)data_write(&incl_len, sizeof(incl_len), 1); + (void)data_write(&orig_len, sizeof(orig_len), 1); + if (header_len == 1) { + header[0] = mstp_port->DataRegister; + } else if (header_len == 2) { + header[0] = 0x55; + header[1] = mstp_port->DataRegister; + } else { + header[0] = 0x55; + header[1] = 0xFF; + header[2] = mstp_port->FrameType; + header[3] = mstp_port->DestinationAddress; + header[4] = mstp_port->SourceAddress; + header[5] = HI_BYTE(mstp_port->DataLength); + header[6] = LO_BYTE(mstp_port->DataLength); + header[7] = mstp_port->HeaderCRCActual; + } + (void)data_write(header, header_len, 1); + if (max_data) { + (void)data_write(mstp_port->InputBuffer, max_data, 1); + (void)data_write((char *)&mstp_port->DataCRCActualMSB, 1, 1); + (void)data_write((char *)&mstp_port->DataCRCActualLSB, 1, 1); } } @@ -672,55 +689,55 @@ static bool test_global_header(const char *filename) size_t count = 0; /* open existing file. */ - pFile = fopen(filename, "rb"); - if (pFile) { - count = fread(&magic_number, sizeof(magic_number), 1, pFile); + File_Handle = fopen(filename, "rb"); + if (File_Handle) { + count = fread(&magic_number, sizeof(magic_number), 1, File_Handle); if ((count != 1) || (magic_number != 0xa1b2c3d4)) { fprintf(stderr, "mstpcap: invalid magic number\n"); - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&version_major, sizeof(version_major), 1, pFile); + count = fread(&version_major, sizeof(version_major), 1, File_Handle); if ((count != 1) || (version_major != 2)) { fprintf(stderr, "mstpcap: invalid major version\n"); - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&version_minor, sizeof(version_minor), 1, pFile); + count = fread(&version_minor, sizeof(version_minor), 1, File_Handle); if ((count != 1) || (version_minor != 4)) { fprintf(stderr, "mstpcap: invalid minor version\n"); - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&thiszone, sizeof(thiszone), 1, pFile); + count = fread(&thiszone, sizeof(thiszone), 1, File_Handle); if ((count != 1) || (thiszone != 0)) { fprintf(stderr, "mstpcap: invalid time zone\n"); - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&sigfigs, sizeof(sigfigs), 1, pFile); + count = fread(&sigfigs, sizeof(sigfigs), 1, File_Handle); if ((count != 1) || (sigfigs != 0)) { fprintf(stderr, "mstpcap: invalid time stamp accuracy\n"); - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&snaplen, sizeof(snaplen), 1, pFile); + count = fread(&snaplen, sizeof(snaplen), 1, File_Handle); if (count != 1) { fprintf(stderr, "mstpcap: unable to read SNAP length\n"); - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&network, sizeof(network), 1, pFile); + count = fread(&network, sizeof(network), 1, File_Handle); if ((count != 1) || (network != DLT_BACNET_MS_TP)) { fprintf(stderr, "mstpcap: invalid data link type (DLT)\n"); - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } } else { @@ -743,37 +760,37 @@ static bool read_received_packet(volatile struct mstp_port_struct_t *mstp_port) size_t count = 0; unsigned i = 0; - if (pFile) { - count = fread(&ts_sec, sizeof(ts_sec), 1, pFile); + if (File_Handle) { + count = fread(&ts_sec, sizeof(ts_sec), 1, File_Handle); if (count != 1) { - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&ts_usec, sizeof(ts_usec), 1, pFile); + count = fread(&ts_usec, sizeof(ts_usec), 1, File_Handle); if (count != 1) { - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } tv.tv_sec = ts_sec; tv.tv_usec = ts_usec; - count = fread(&incl_len, sizeof(incl_len), 1, pFile); + count = fread(&incl_len, sizeof(incl_len), 1, File_Handle); if (count != 1) { - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&orig_len, sizeof(orig_len), 1, pFile); + count = fread(&orig_len, sizeof(orig_len), 1, File_Handle); if (count != 1) { - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread(&header, sizeof(header), 1, pFile); + count = fread(&header, sizeof(header), 1, File_Handle); if (count != 1) { - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } mstp_port->FrameType = header[2]; @@ -801,22 +818,22 @@ static bool read_received_packet(volatile struct mstp_port_struct_t *mstp_port) /* packet includes data */ mstp_port->DataLength = orig_len - 8 - 2; count = - fread(mstp_port->InputBuffer, mstp_port->DataLength, 1, pFile); + fread(mstp_port->InputBuffer, mstp_port->DataLength, 1, File_Handle); if (count != 1) { - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread((char *)&mstp_port->DataCRCActualMSB, 1, 1, pFile); + count = fread((char *)&mstp_port->DataCRCActualMSB, 1, 1, File_Handle); if (count != 1) { - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } - count = fread((char *)&mstp_port->DataCRCActualLSB, 1, 1, pFile); + count = fread((char *)&mstp_port->DataCRCActualLSB, 1, 1, File_Handle); if (count != 1) { - fclose(pFile); - pFile = NULL; + fclose(File_Handle); + File_Handle = NULL; return false; } mstp_port->DataCRC = 0xFFFF; @@ -858,11 +875,11 @@ static void cleanup(void) if (!Wireshark_Capture) { packet_statistics_print(); } - if (pFile) { - fflush(pFile); /* stream pointer */ - fclose(pFile); /* stream pointer */ + if (File_Handle) { + fflush(File_Handle); /* stream pointer */ + fclose(File_Handle); /* stream pointer */ } - pFile = NULL; + File_Handle = NULL; } #if defined(_WIN32) @@ -870,11 +887,11 @@ static BOOL WINAPI CtrlCHandler(DWORD dwCtrlType) { dwCtrlType = dwCtrlType; - if (hPipe != INVALID_HANDLE_VALUE) { - FlushFileBuffers(hPipe); - DisconnectNamedPipe(hPipe); - CloseHandle(hPipe); - hPipe = INVALID_HANDLE_VALUE; + if (Pipe_Handle != INVALID_HANDLE_VALUE) { + FlushFileBuffers(Pipe_Handle); + DisconnectNamedPipe(Pipe_Handle); + CloseHandle(Pipe_Handle); + Pipe_Handle = INVALID_HANDLE_VALUE; } /* signal to main loop to exit */ Exit_Requested = true; @@ -904,16 +921,6 @@ static void signal_init(void) } #endif -static void filename_create_new(void) -{ - if (pFile) { - fclose(pFile); - } - pFile = NULL; - filename_create(&Capture_Filename[0]); - write_global_header(&Capture_Filename[0]); -} - static void print_usage(char *filename) { printf("Usage: %s", filename); @@ -931,9 +938,9 @@ static void print_help(char *filename) filename); printf("\n"); printf("Captures MS/TP packets from a serial interface\n" - "and saves them to a file. Saves packets in a\n" - "filename mstp_20090123091200.cap that has data and time.\n" - "After receiving 65535 packets, a new file is created.\n"); + "and writes them to a file or a pipe, or scans a file for stats." + "Filename is of the form mstp_20090123091200.cap (timestamp).\n" + "New files are created after receiving 65535 packets.\n"); printf("\n"); printf("Command line options:\n" "[--extcap-interface port] - serial interface.\n" @@ -1144,6 +1151,7 @@ int main(int argc, char *argv[]) signal_init(); #endif filename_create_new(); + write_global_header(); /* run forever */ for (;;) { RS485_Check_UART_Data(mstp_port); @@ -1196,11 +1204,13 @@ int main(int argc, char *argv[]) if (!(packet_count % 100)) { fprintf(stdout, "\r%u packets, %u invalid frames", (unsigned)packet_count, (unsigned)Invalid_Frame_Count); + fflush(stdout); } if (packet_count >= 65535) { packet_statistics_print(); packet_statistics_clear(); filename_create_new(); + write_global_header(); packet_count = 0; } }