#include #include #include #include #include #include volatile sig_atomic_t shutdown_flag = 0; void handle_sigint(int sig) { shutdown_flag = 1; } int main(int argc, char *argv[]) { struct sigaction sa; sa.sa_handler = handle_sigint; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGINT, &sa, NULL); FILE *input = stdin; int buffer_size = 4096; // Parse command line arguments // -f filename (optional) // b buffer_size (optional) char opt; while ((opt = getopt(argc, argv, "f:b:")) != -1) { switch (opt) { case 'f': input = fopen(optarg, "r"); if (input == NULL) { fprintf(stderr, "Error: Could not open input file\n"); return EXIT_FAILURE; } break; case 'b': buffer_size = atoi(optarg); break; default: printf("Usage: %s [-f filename] [-b buffer_size]\n", argv[0]); return 1; } } // Allocate buffer char *buffer = malloc(buffer_size); // Read from input and write to stdout while (fgets(buffer, buffer_size, input) != NULL) { fwrite(buffer, sizeof(char), strlen(buffer), stdout); // Handle shutdown if (shutdown_flag) { fprintf(stderr, "Cancelled\n"); return 1; } } // Cleanup free(buffer); return 0; }