Add option '--exec <command>' for running shell command

Runs shell command with I/O redirected to device.
This commit is contained in:
Martin Lund 2024-05-07 14:38:19 +02:00
parent 545d473220
commit e75e19eb00
9 changed files with 89 additions and 10 deletions

View file

@ -45,6 +45,7 @@ _tio()
--script \
--script-file \
--script-run \
--exec \
-v --version \
-h --help"
@ -179,6 +180,10 @@ _tio()
COMPREPLY=( $(compgen -W "once always never" -- ${cur}) )
return 0
;;
--exec)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
;;
-v | --version)
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0

View file

@ -282,6 +282,7 @@ static void config_parse_keys(GKeyFile *key_file, char *group)
g_free((void *)string);
string = NULL;
}
config_get_string(key_file, group, "exec", &option.exec, NULL);
config_get_string(key_file, group, "prefix-ctrl-key", &string, NULL);
if (string != NULL)
{

View file

@ -33,6 +33,7 @@
#include <time.h>
#include <errno.h>
#include <sys/poll.h>
#include <sys/wait.h>
#include <termios.h>
#include <fnmatch.h>
#include "error.h"
@ -199,3 +200,61 @@ bool match_patterns(const char *string, const char *patterns)
free(patterns_copy);
return false;
}
// Function that forks subprocess, redirects its stdin and stdout to the
// specified filedescriptor, and runs command.
int execute_shell_command(int fd, const char *command)
{
pid_t pid;
int status;
// Fork a child process
pid = fork();
if (pid == -1)
{
// Error occurred
tio_error_print("fork() failed (%s)", strerror(errno));
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
// Child process
tio_printf("Executing shell command '%s'", command);
// Redirect stdout and stderr to the file descriptor
if (dup2(fd, STDOUT_FILENO) == -1 || dup2(fd, STDERR_FILENO) == -1)
{
tio_error_print("dup2() failed (%s)", strerror(errno));
exit(EXIT_FAILURE);
}
// Execute the shell command
execl("/bin/sh", "sh", "-c", command, (char *)NULL);
// If execlp() returns, it means an error occurred
perror("execlp");
tio_error_print("execlp() failed (%s)", strerror(errno));
exit(EXIT_FAILURE);
}
else
{
// Parent process
// Wait for the child process to finish
waitpid(pid, &status, 0);
if (WIFEXITED(status))
{
tio_printf("Command exited with status %d", WEXITSTATUS(status));
return WEXITSTATUS(status);
}
else
{
tio_error_printf("Child process exited abnormally\n");
return -1;
}
}
return 0;
}

View file

@ -34,3 +34,4 @@ char *base62_encode(unsigned long num);
int read_poll(int fd, void *data, size_t len, int timeout);
double get_current_time(void);
bool match_patterns(const char *string, const char *patterns);
int execute_shell_command(int fd, const char *command);

View file

@ -69,6 +69,7 @@ enum opt_t
OPT_EXCLUDE_DEVICES,
OPT_EXCLUDE_DRIVERS,
OPT_EXCLUDE_TIDS,
OPT_EXEC,
};
/* Default options */
@ -121,6 +122,7 @@ struct option_t option =
.exclude_tids = NULL,
.hex_n_value = 0,
.vt100 = false,
.exec = NULL,
};
void option_print_help(char *argv[])
@ -167,6 +169,7 @@ void option_print_help(char *argv[])
printf(" --script <string> Run script from string\n");
printf(" --script-file <filename> Run script from file\n");
printf(" --script-run once|always|never Run script on connect (default: always)\n");
printf(" --exec <command> Execute shell command with I/O redirected to device\n");
printf(" -v, --version Display version\n");
printf(" -h, --help Display help\n");
printf("\n");
@ -815,6 +818,7 @@ void options_parse(int argc, char *argv[])
{"script", required_argument, 0, OPT_SCRIPT },
{"script-file", required_argument, 0, OPT_SCRIPT_FILE },
{"script-run", required_argument, 0, OPT_SCRIPT_RUN },
{"exec", required_argument, 0, OPT_EXEC },
{"version", no_argument, 0, 'v' },
{"help", no_argument, 0, 'h' },
{"complete-profiles", no_argument, 0, OPT_COMPLETE_PROFILES },
@ -985,6 +989,10 @@ void options_parse(int argc, char *argv[])
option_parse_script_run(optarg, &option.script_run);
break;
case OPT_EXEC:
option.exec = optarg;
break;
case 'v':
printf("tio v%s\n", VERSION);
exit(EXIT_SUCCESS);

View file

@ -96,6 +96,7 @@ struct option_t
char *exclude_tids;
int hex_n_value;
bool vt100;
char *exec;
};
extern struct option_t option;

View file

@ -2277,6 +2277,12 @@ int tty_connect(void)
exit(EXIT_SUCCESS);
}
if (option.exec != NULL)
{
int status = execute_shell_command(device_fd, option.exec);
exit(status);
}
/* Input loop */
while (true)
{