#include #include #include #include #include #include #include volatile sig_atomic_t shutdown_flag = 0; volatile sig_atomic_t stats_flag = 0; void handle_sigint(int sig) { shutdown_flag = 1; } void handle_sigusr1(int sig) { stats_flag = 1; } int main(int argc, char *argv[]) { struct sigaction sa_sigint; sa_sigint.sa_handler = handle_sigint; sigemptyset(&sa_sigint.sa_mask); sa_sigint.sa_flags = 0; sigaction(SIGINT, &sa_sigint, NULL); struct sigaction sa_sigusr1; sa_sigusr1.sa_handler = handle_sigusr1; sigemptyset(&sa_sigusr1.sa_mask); sa_sigusr1.sa_flags = 0; sigaction(SIGUSR1, &sa_sigusr1, NULL); int max_lines = -1; // -1 means unlimited int verbose = 0; // Parse arguments (-n max_lines, -v verbose) char opt; while ((opt = getopt(argc, argv, "n:v")) != -1) { switch (opt) { case 'n': max_lines = atoi(optarg); break; case 'v': verbose = 1; break; default: printf("Usage: %s [-n max_lines] [-v]\n", argv[0]); return 1; } } clock_t start = clock(); // Read from stdin line by line // Count lines and characters // If verbose, echo lines to stdout char buffer[256]; int lines = 0; int chars = 0; while (fgets(buffer, sizeof(buffer), stdin) != NULL) { int size = strlen(buffer); if (verbose) fwrite(buffer, sizeof(char), size, stdout); chars += size; if (size > 0 && buffer[size - 1] == '\n') lines++; if (lines == max_lines) break; // Handle shutdown if (shutdown_flag) { fprintf(stderr, "Cancelled\n"); return 1; } } // Print statistics to stderr (handle SIGUSR1) if (stats_flag) { clock_t end = clock(); double time = ((double)(end - start)) / CLOCKS_PER_SEC; double throughput = (double)chars / 1024.0 / 1024.0 / time; printf("Stats:\n"); printf("File Size: %d bytes\n", chars); printf("Total Time: %.3f secs\n", time); printf("Throughput: %.3f MB/s\n", throughput); } fprintf(stderr, "Lines: %d\n", lines); return 0; }