Comment utiliser un programme C pour exécuter une commande sur le terminal?

11

Je veux créer un programme en langage C qui me permettrait d'exécuter une commande dans le terminal.

J'ai créé un programme en script shell qui me donnerait l'IP de n'importe quel site Web ouvert dans mon navigateur. Ce script shell est exécuté en entrant cette commande dans le terminal:

sudo tcpdump -n dst port 80 -i eth

Mon professeur m'a dit de créer un programme en langage C qui ouvrirait le terminal et entrerait cette commande, puis mon script shell fonctionnerait.

Veuillez me dire comment créer un tel programme.

Tehseen Malik
la source

Réponses:

8

vous pouvez utiliser la fonction system () disponible dans stdlib.h pour exécuter les commandes.

LA DESCRIPTION

system () exécute une commande spécifiée dans la chaîne en appelant / bin / sh -c chaîne et retourne une fois la commande terminée. Pendant l'exécution de la commande, SIGCHLD sera bloqué et SIGINT et SIGQUIT seront ignorés.

Vous pouvez en savoir plus à ce sujet ici http://linux.about.com/library/cmd/blcmdl3_system.htm

Mevin Babu
la source
C'est certainement une façon, mais vous ne voulez probablement pas exécuter des commandes à partir d'un programme alternatif, à la place, la plupart des programmes Linux ont une bibliothèque qui peut juste directement le code des programmes. Par exemple, ssh peut utiliser libssh . Il y a généralement une raison TRÈS limitée d'exécuter des commandes système à partir du code. Si vous y allez beaucoup, vous faites presque certainement quelque chose de mal.
coteyr
J'ai fait un programme en C comme ça
Tehseen Malik
4

Bonjour, je vais vous écrire un exemple de code, vous l'expliquer et j'espère vraiment que cela vous aidera. le prototype de la fonction est quelque chose comme:

système int (const char * cmd);

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_CMN_LEN 100

int main(int argc, char *argv[])
{
    char cmd[MAX_CMN_LEN] = "", **p;

    if (argc < 2) /*no command specified*/
    {
        fprintf(stderr, "Usage: ./program_name terminal_command ...");
        exit(EXIT_FAILURE);
    }
    else
    {
        strcat(cmd, argv[1]);
        for (p = &argv[2]; *p; p++)
        {
            strcat(cmd, " ");
            strcat(cmd, *p);
        }
        system(cmd);
    }

    return 0;
}

1). ouvrir un terminal et compiler le programme

2). exécutez-le (par exemple dans Ubuntu) ./program_name nom_comman -anything - n'importe quoi

exemple: ./a.out locale -a

cet exemple affiche tous les paramètres régionaux pris en charge par mon compilateur qui est gcc.

Plus d'informations:

p est un poniter pour pointer vers char (comme argv est) p = & argv [2], pointe sur -toute chaîne i cat all -anythings sur ma chaîne cmd je quitte la boucle lorsque * p pointe sur NULL regardez ceci: -> j'utiliserai ce symbole pour dire des points (ne le confondez pas avec l'opérateur de sélection de la flèche droite).

argv [0] -> nom_programme

argv [1] -> nom_commande (dans cet exemple, le nom de la commande sera locale, mais entrez la commande que vous souhaitez vérifier à la place)

argv [2] -> -anything (dans cet exemple -a, qui est tous les locales)

argv [3] -> NULL (dans cet exemple, cela quitte la boucle)

ok c'est tout, je pense.

NEMKA
la source
Assurez-vous de ne pas l'utiliser comme un exécutable setuid, car il a un exploit évident de dépassement de tampon.
Martin
0

Je vais supposer qu'il s'agit d'utiliser un binaire setuid-root pour remplacer sudo, plutôt que d'exécuter simplement des commandes arbitraires, donc je vais inclure les autres parties de la solution.

Pour des raisons de sécurité, nous évitons system () car il peut être détourné.

Après avoir compilé cela, installez le binaire résultant en tant que setuid-root.

#include <unistd.h>
#include <stdio.h>
#include <sysexits.h>

int main (int argc, char ** argv) {
    if (argc> 2) {fputs ("trop ​​d'arguments \ n", stderr); return EX_USAGE; }
    if (argc> 1 && argv [1] [0] == '-') {fputs ("aucune option autorisée \ n", stderr); return EX_USAGE; }
    if (geteuid ()! = 0) {fputs ("pas correctement installé en tant que setuid-root \ n", stderr); retour EX_UNAVAILABLE; }
    if (setuid (0) 1) p [6] = argv [1];

    / * Si tout se passe bien, execv ne reviendra pas
     * (car ce programme aura été remplacé par tcpdump) * /
    execv (p0, p);
    / * si nous arrivons ici, alors execv doit avoir échoué * /

    perror (p0);
    return EX_OSFILE;
}

si vous l'avez enregistré sous foo.cet souhaitez qu'il soit installé sous /usr/local/sbin/foo, exécutez:

make foo && install -o root -m 4511 foo / usr / local / sbin / foo
Martin
la source