Created
June 19, 2025 04:20
-
-
Save konsolebox/203ec311af1d37da4aec37e36f47248b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Runs command while optionally redirecting stdout, | |
* stderr and stdin to a file prior and not | |
* making any changes to the environment. | |
* | |
* Author: Grok | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
void print_help(const char *progname) { | |
printf("Usage: %s [options] command [args...]\n", progname); | |
printf("Run a command with optional redirected output/input, preserving the environment.\n\n"); | |
printf("Options:\n"); | |
printf(" --stdout <file> Redirect stdout to <file>\n"); | |
printf(" --stderr <file> Redirect stderr to <file>\n"); | |
printf(" --stdin <file> Redirect stdin from <file>\n"); | |
printf(" --help Show this help message and exit\n"); | |
printf("\nNotes:\n"); | |
printf(" - Options are optional and must appear before the command or '--'.\n"); | |
printf(" - If an option is not specified, the corresponding stream is not redirected.\n"); | |
printf(" - Use '--' to separate options from arguments that look like options.\n"); | |
printf("Example:\n"); | |
printf(" %s --stdout out.txt --stderr err.txt /bin/echo hello\n", progname); | |
exit(0); | |
} | |
int main(int argc, char *argv[], char *envp[]) { | |
const char *stdout_file = NULL; | |
const char *stderr_file = NULL; | |
const char *stdin_file = NULL; | |
int i; | |
int cmd_start = 0; | |
// Parse arguments | |
for (i = 1; i < argc; i++) { | |
if (strcmp(argv[i], "--help") == 0) { | |
print_help(argv[0]); | |
} else if (strcmp(argv[i], "--") == 0) { | |
cmd_start = i + 1; | |
break; | |
} else if (strcmp(argv[i], "--stdout") == 0) { | |
if (i + 1 >= argc) { | |
fprintf(stderr, "Error: --stdout requires a file argument\n"); | |
return 1; | |
} | |
stdout_file = argv[++i]; | |
} else if (strcmp(argv[i], "--stderr") == 0) { | |
if (i + 1 >= argc) { | |
fprintf(stderr, "Error: --stderr requires a file argument\n"); | |
return 1; | |
} | |
stderr_file = argv[++i]; | |
} else if (strcmp(argv[i], "--stdin") == 0) { | |
if (i + 1 >= argc) { | |
fprintf(stderr, "Error: --stdin requires a file argument\n"); | |
return 1; | |
} | |
stdin_file = argv[++i]; | |
} else { | |
// Non-option argument; start of command | |
cmd_start = i; | |
break; | |
} | |
} | |
// Check if a command was provided | |
if (cmd_start == 0 || cmd_start >= argc) { | |
fprintf(stderr, "No command specified\n"); | |
return 1; | |
} | |
// Redirect stdin if specified | |
if (stdin_file) { | |
int stdin_fd = open(stdin_file, O_RDONLY); | |
if (stdin_fd == -1) { | |
perror("Failed to open stdin file"); | |
return 1; | |
} | |
if (dup2(stdin_fd, STDIN_FILENO) == -1) { | |
perror("Failed to redirect stdin"); | |
return 1; | |
} | |
close(stdin_fd); | |
} | |
// Redirect stdout if specified | |
if (stdout_file) { | |
int stdout_fd = open(stdout_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
if (stdout_fd == -1) { | |
perror("Failed to open stdout file"); | |
return 1; | |
} | |
if (dup2(stdout_fd, STDOUT_FILENO) == -1) { | |
perror("Failed to redirect stdout"); | |
return 1; | |
} | |
close(stdout_fd); | |
} | |
// Redirect stderr if specified | |
if (stderr_file) { | |
int stderr_fd = open(stderr_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); | |
if (stderr_fd == -1) { | |
perror("Failed to open stderr file"); | |
return 1; | |
} | |
if (dup2(stderr_fd, STDERR_FILENO) == -1) { | |
perror("Failed to redirect stderr"); | |
return 1; | |
} | |
close(stderr_fd); | |
} | |
// Detach from terminal | |
if (setsid() == -1) { | |
perror("Failed to detach from terminal"); | |
return 1; | |
} | |
// Execute the command with the inherited environment | |
execvpe(argv[cmd_start], &argv[cmd_start], envp); | |
perror("Failed to execute command"); | |
return 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment