Maison >développement back-end >Golang >Comment puis-je créer un programme qui imite un terminal (TTY) sous Linux et macOS ?

Comment puis-je créer un programme qui imite un terminal (TTY) sous Linux et macOS ?

Susan Sarandon
Susan Sarandonoriginal
2024-12-01 06:41:17219parcourir

How Can I Create a Program That Mimics a Terminal (TTY) on Linux and macOS?

Créer un programme déguisé en ATS

Dans de nombreux scénarios, les programmes scrutent la nature de stdin, discernant s'il s'agit d'un terminal (ATS) ou un tube utilisant des fonctions spécialisées comme isatty. Cette distinction incite les programmes à générer des résultats différemment. Pour relever ce défi, nous explorerons comment construire un programme capable de se faire passer pour un ATS.

Une solution pour Linux et macOS

L'extrait de code ci-dessous illustre une solution viable pour Linux et macOS. Il exploite l'interface pty, offrant la fonctionnalité permettant d'exécuter des commandes dans un pseudo-terminal, trompant efficacement les programmes en les faisant interpréter l'entrée comme provenant d'un TTY :

#include <signal.h>
#include <stdlib.h>
#include <sysexits.h>
#include <unistd.h>
#include <util.h>

pid_t child = 0;

void sighandler(int signum) {
  if (child > 0) {
    killpg(child, signum);
    exit(signum);
  }
}

int main(int argc, char *argv[]) {
  if (argc < 2) {
    return EX_USAGE;
  }

  int master;
  child = forkpty(&amp;master, NULL, NULL, NULL);
  // Forkpty setup: master (parent) and child (command execution)

  if (child == -1) {
    perror("failed to fork pty");
    return EX_OSERR;
  }

  if (child == 0) {
    execvp(argv[1], argv + 1);
    // Execute the specified command within the pty
  }

  signal(SIGHUP, sighandler);
  signal(SIGINT, sighandler);
  signal(SIGTERM, sighandler);
  // Trap signals and forward them to the child

  const int buf_size = 1024;
  char buf[buf_size];
  fd_set fds;
  ssize_t bytes_read;
  // I/O management variables

  while (1) {
    FD_ZERO(&amp;fds);
    FD_SET(master, &amp;fds);
    // Set up file descriptor set and monitor master (pty)

    if (select(master + 1, &amp;fds, NULL, NULL, NULL) > 0 &amp;&amp; FD_ISSET(master, &amp;fds)) {
      bytes_read = read(master, buf, buf_size);
      if (bytes_read <= 0) {
        return EXIT_SUCCESS;
      }

      if (write(STDOUT_FILENO, buf, bytes_read) != bytes_read) {
        perror("failed to write to stdout");
        return EX_OSERR;
      }
    }
  }
}

Ce code établit un canal de communication entre un processus parent et un processus enfant exécuté dans un pty. Le processus parent lit en permanence le pty et transmet son contenu à la sortie standard, simulant ainsi efficacement le comportement d'un TTY standard.

La mise en œuvre de cette approche permet à votre programme de contourner les contraintes potentielles imposées par les programmes attendant une entrée d'un TTY. Il permet à votre programme de manipuler et de transformer les entrées tout en conservant l'apparence d'un terminal.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn