// // netlog1.exe - Simple network port data logger. // // - Read data from given IP address:port. // - Write lines to log file (and echo to stdout). // - Optional parameter to take only one of every Nth line. // - Log file is sync'd periodically to protect data. // // 06-Sep-2007 tvb // #include #include #include char Usage[] = "\n" "Usage: netlog [addr:port] [logfile] [nth]\n" "\n" "Example:\n" " netlog 192.168.0.120:1298 tsc5120.dat\n" " netlog 192.168.0.120:1298 tsc5120.1Hz 1000\n" ; // Declare function prototypes. void LogOpen1 (char *path); void LogWrite (char *buf, int size); void LogClose (void); void NetOpen1 (char *addr_port); void NetClose (void); int NetRead (char *buffer, int size); int line_length (char *buf, int size); int main (int argc, char *argv[]) { long line_count; int nth; if (argc < 3) { fprintf(stderr, Usage); exit(1); } // Open network connection and log file. NetOpen1(argv[1]); LogOpen1(argv[2]); // Get optional data reduction factor (decimation). nth = (argc > 3) ? max(atoi(argv[3]), 1) : 1; fprintf(stderr, "** Taking one of every %d lines\n", nth); // Main loop: read from network, isolate lines, write to log file. line_count = 0; while (1) { char buffer[5000]; long offset, resid, length; resid = NetRead(buffer, sizeof buffer); if (resid <= 0) { break; } for (offset = 0; resid > 0; offset += length, resid -= length) { // Write full line (or fragment of line) at a time. length = line_length(buffer + offset, resid); if ((line_count % nth) == 0) { LogWrite(buffer + offset, length); } // Increment count if full line (or final fragment of line). if (buffer[offset + length - 1] == '\n') { line_count += 1; } } } LogClose(); NetClose(); return 0; } // // Find length of delimited line in buffer. // int line_length (char *buf, int size) { int i; for (i = 0; i < size; i += 1) { if (buf[i] == '\n') { return i + 1; } } return size; } // ------------------------------------------------------------------------ // // // Log functions. // char *LogPath; FILE *LogFile; #ifdef _WIN32 char *LogMode = "ab"; #else char *LogMode = "a"; #endif // Open log file for append. void LogOpen1 (char *path) { LogPath = path; LogFile = fopen(LogPath, LogMode); if (LogFile == NULL) { fprintf(stderr, "%s: log file open failed\n", LogPath); exit(1); } fprintf(stderr, "** Appending to log file: %s\n", LogPath); return; } // Close log file. void LogClose (void) { fclose(LogFile); LogFile = NULL; return; } // Sync log file to disk once every minute (to protect the data). #include void LogSync (void) { static int once = 1; static long t1, t2; if (once) { t1 = clock(); once = 0; } t2 = clock(); if (((t2 - t1) / CLOCKS_PER_SEC) > 60) { fclose(LogFile); LogFile = fopen(LogPath, LogMode); if (LogFile == NULL) { fprintf(stderr, "%s: log file re-open failed\n", LogPath); exit(1); } t1 = t2; } return; } // Write data to both log and stdout. void LogWrite (char *buf, int size) { fwrite(buf, size, 1, LogFile); fwrite(buf, size, 1, stdout); LogSync(); return; } // ------------------------------------------------------------------------ // // // Win32/BSD network functions. // #ifdef _WIN32 #include SOCKET sock; #define ERRNO h_errno #else #include #include #include int sock; #include #define ERRNO errno #endif // Open network connection. void NetOpen1 (char *addr_port) { char *addr, *p; short port; struct sockaddr_in sin; int n; char note[20] = ""; static int once = 1; if ((p = strchr(addr_port, ':')) != NULL) { addr = addr_port; *p = '\0'; port = atoi(p + 1); } else { fprintf(stderr, "%s: missing port number\n", addr_port); exit(1); } #ifdef _WIN32 if (once) { WSADATA WSAData; WSAStartup(MAKEWORD(1,1), &WSAData); sprintf(note, " (WSA %d.%d)", LOBYTE(WSAData.wVersion), HIBYTE(WSAData.wVersion)); once = 0; } #endif fprintf(stderr, "** Connecting to %s, port %d%s\n", addr, port, note); sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { fprintf(stderr, "socket failed (%ld)\n", ERRNO); exit(1); } memset((char *)&sin, 0x0, sizeof sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr(addr); sin.sin_port = htons(port); n = connect(sock, (struct sockaddr *)&sin, sizeof sin ); if (n < 0) { fprintf(stderr, "connect failed (%ld)\n", ERRNO); exit(1); } return; } // Close network connection. void NetClose (void) { #ifdef _WIN32 WSACleanup(); #endif return; } // Blocking read from IP port. int NetRead (char *buffer, int size) { int n; n = recv(sock, buffer, size, 0); if (n < 0) { fprintf(stderr, "Network read error (%ld)\n", ERRNO); } return n; }