Jak użyć programu C do uruchomienia polecenia na terminalu?

11

Chcę stworzyć program w języku C, który pozwoliłby mi uruchomić polecenie w terminalu.

Zrobiłem program w skrypcie powłoki, który dałby mi ip każdej strony internetowej, która jest otwarta w mojej przeglądarce. Ten skrypt powłoki jest wykonywany przez wpisanie tego polecenia w terminalu:

sudo tcpdump -n dst port 80 -i eth

Mój profesor kazał mi stworzyć program w języku C, który otworzyłby terminal i wprowadził to polecenie, a następnie działałby mój skrypt powłoki.

Powiedz mi, jak stworzyć taki program.

Tehseen Malik
źródło

Odpowiedzi:

8

możesz użyć funkcji system () dostępnej w stdlib.h do uruchamiania poleceń.

OPIS

system () wykonuje polecenie określone w ciągu poprzez wywołanie ciągu / bin / sh -c i powraca po zakończeniu polecenia. Podczas wykonywania polecenia SIGCHLD zostanie zablokowany, a SIGINT i SIGQUIT zostaną zignorowane.

Możesz przeczytać więcej na ten temat tutaj http://linux.about.com/library/cmd/blcmdl3_system.htm

Mevin Babu
źródło
Jest to z pewnością jeden sposób, ale prawdopodobnie nie chcesz uruchamiać poleceń z programu ac, zamiast tego większość programów Linuksa ma bibliotekę, która może bezpośrednio kodować programy. Na przykład ssh może używać libssh . Zwykle istnieje bardzo ograniczony powód, aby uruchamiać polecenia systemowe z kodu. Jeśli często to robisz, prawie na pewno robisz coś złego.
coteyr
Zrobiłem program w C w ten sposób
Tehseen Malik,
4

Witaj, napiszę dla ciebie przykładowy kod, wyjaśnię go i mam nadzieję, że to ci pomoże. prototyp funkcji jest podobny do:

int system (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). otwórz terminal i skompiluj program

2). uruchom go (na przykład w Ubuntu) ./nazwa_programu nazwa_programu -wszystko - cokolwiek

przykład: ./a.out locale -a

ten przykład wyświetla wszystkie ustawienia narodowe obsługiwane przez mój kompilator, którym jest gcc.

więcej informacji:

p to poniter do wskaźnika na char (jak argv jest) p = & argv [2], wskazuje na dowolny ciąg i cat wszystko-wszystko na mój ciąg cmd wychodzę z pętli, gdy * p wskazuje na NULL spójrz na to: -> użyję tego symbolu, aby powiedzieć punkty (nie mylić go z operatorem wyboru prawej strzałki).

argv [0] -> nazwa_programu

argv [1] -> nazwa_ polecenia (w tym przykładzie nazwa polecenia będzie ustawieniem regionalnym, ale zamiast tego wprowadź polecenie, które chcesz sprawdzić)

argv [2] -> -anything (w tym przykładzie -a, czyli wszystkie ustawienia narodowe)

argv [3] -> NULL (w tym przykładzie powoduje to zamknięcie pętli)

ok, to wszystko, tak myślę.

NEMKA
źródło
Upewnij się, że nie używasz tego jako pliku wykonywalnego setuid, ponieważ ma oczywisty exploit przepełnienia bufora.
Martin
0

Zakładam, że chodzi tu o użycie pliku binarnego z setuid-root do zastąpienia sudo, a nie tylko o wykonanie dowolnego polecenia, więc dołączę inne części rozwiązania.

Ze względów bezpieczeństwa unikamy system (), ponieważ można go przejąć.

Po kompilacji zainstaluj wynikowy plik binarny jako setuid-root.

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

int main (int argc, char ** argv) {
    if (argc> 2) {fputs ("too many args \ n", stderr); zwróć EX_USAGE; }
    if (argc> 1 && argv [1] [0] == '-') {fputs („bez opcji dozwolone \ n”, stderr); zwróć EX_USAGE; }
    if (geteuid ()! = 0) {fputs ("niepoprawnie zainstalowany jako root setuid \ n", stderr); zwróć EX_UNAVAILABLE; }
    if (setuid (0) 1) p [6] = argv [1];

    / * Jeśli wszystko pójdzie dobrze, execv nie zwróci
     * (ponieważ ten program zostanie zastąpiony przez tcpdump) * /
    execv (p0, p);
    / * jeśli tutaj dotrzemy, to wykonanie polecenia execv nie powiodło się * /

    perror (p0);
    zwraca EX_OSFILE;
}

jeśli zapisałeś to jako foo.ci chcesz zainstalować jako /usr/local/sbin/foo, uruchom:

zrób foo && install -o root -m 4511 foo / usr / local / sbin / foo
Jaskółka oknówka
źródło