La fonction system() en C++

Jinku Hu 12 octobre 2023
  1. Utilisez la fonction system() en C++ pour exécuter la commande Shell
  2. Utilisez system(nullptr) pour vérifier si le shell est disponible sur le système
  3. Utilisez les macros wstatus pour vérifier l’état de la commande exécutée
La fonction system() en C++

Cet article présentera plusieurs méthodes d’utilisation d’une fonction de bibliothèque - system() en C++.

Utilisez la fonction system() en C++ pour exécuter la commande Shell

La fonction system() fait partie de la bibliothèque standard C depuis un certain temps, et elle peut également être incluse dans le code C++ sans bibliothèques supplémentaires. La fonction est utilisée pour exécuter une commande shell à partir du processus appelant. Notez cependant que system est créé pour des cas d’utilisation spéciaux lorsque le programme appelant doit générer un seul processus enfant et commencer immédiatement à attendre sa fin. Ainsi, la fonction elle-même est implémentée avec plusieurs appels système disponibles dans le cadre de l’interface système.

Si nous supposons l’environnement UNIX, l’utilisateur n’a pas à traiter directement avec les fonctions fork, exec et wait qui contrôlent la création/le nettoyage d’un nouveau processus. L’exemple suivant illustre le cas d’utilisation le plus simple de la fonction system, qui exécute l’utilitaire de ligne de commande ls pour imprimer les fichiers dans le répertoire de travail actuel.

#include <iostream>

int main() {
  system("ls");

  return EXIT_SUCCESS;
}

La fonction system() crée généralement deux processus pour exécuter une seule commande. A savoir, il crée un shell avec un appel exec et un autre pour la commande donnée que le shell exécutera. Cela affecte négativement les performances par rapport à l’utilisation directe des appels système sous-jacents. Notez que si nous exécutons la commande top avec system, le programme attend que l’utilisateur quitte top manuellement, ce qui reviendra dans le processus appelant et le forcera à passer à l’instruction return comme indiqué dans le exemple suivant.

#include <iostream>

int main() {
  system("top");

  return EXIT_SUCCESS;
}

Utilisez system(nullptr) pour vérifier si le shell est disponible sur le système

La fonction system() prend une seule chaîne de caractères comme argument, qui est la commande qui doit être exécutée depuis le shell. Si on lui passe nullptr ou NULL, une valeur non nulle est renvoyée lorsqu’un programme shell est disponible sur le système, ou si le zéro est renvoyé, cela indique que le shell n’est pas disponible.

#include <iostream>
#include <string>

using std::cout;
using std::endl;

int main() {
  auto ret = system(nullptr);
  if (ret != 0)
    cout << "shell is available on the system!" << endl;
  else
    cout << "shell is not available on the system!" << endl;

  return EXIT_SUCCESS;
}

Production:

shell is available on the system!

Utilisez les macros wstatus pour vérifier l’état de la commande exécutée

Si l’appel system ne parvient pas à créer un processus enfant, il renvoie -1 et définit errno en conséquence. Si l’appel de fonction réussit, la valeur de retour est le code d’état de fin du shell qui a exécuté la commande donnée. De plus, ce code d’état de fin est le même que le code de sortie de la dernière commande qui a été exécutée. Ainsi, on peut examiner sa valeur à l’aide des macros wstatus décrites dans l’appel système wait page man. L’extrait de code suivant implémente une fonction printWaitStatus pour vérifier la valeur de retour system et afficher les détails de la dernière commande exécutée.

#include <cstring>
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

void printWaitStatus(const char *msg, int status) {
  if (msg != nullptr) printf("%s", msg);

  if (WIFEXITED(status)) {
    printf("child exited, status=%d\n", WEXITSTATUS(status));
  } else if (WIFSIGNALED(status)) {
    printf("child killed by signal %d (%s)", WTERMSIG(status),
           strsignal(WTERMSIG(status)));
#ifdef WCOREDUMP
    if (WCOREDUMP(status)) printf(" (core dumped)");
#endif
    printf("\n");
  } else if (WIFSTOPPED(status)) {
    printf("child stopped by signal %d (%s)\n", WSTOPSIG(status),
           strsignal(WSTOPSIG(status)));
#ifdef WIFCONTINUED
  } else if (WIFCONTINUED(status)) {
    printf("child continued\n");
#endif
  } else {
    printf("status=%x\n", (unsigned int)status);
  }
}

int main() {
  auto ret = system("ls");

  if (ret == -1)
    cout << "a child process could not be created, or"
            "its status could not be retrieved!"
         << endl;
  else
    printWaitStatus(nullptr, ret);

  return EXIT_SUCCESS;
}

Production:

(ls command output)
...
child exited, status=0
Auteur: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook