/ / exec () qualsiasi comando in C - c, linux, shell, execvp

exec () qualsiasi comando in C - c, linux, shell, execvp

Dì in C, voglio chiamare execvp() su qualsiasi comando di stringa. Il comando può essere solo:

char command[] = "ls -l";
char command[] = "rm *.txt";
char command[] = "cat makefile";

Voglio inserire questa variabile di comando all'interno execvp(). Così la exec() la funzione aromatizzata può essere eseguita con qualsiasi tipo di comando arbitrario.

Come lo posso fare? Grazie.

NOTA: system() non è permesso.

risposte:

7 per risposta № 1

Se tu avere chiamare execvp(), quindi sarà necessario suddividere tali stringhe in un nome eseguibile e in una matrice di argomenti (il primo è il "nome" del programma e l'ultimo è un puntatore NULL).

Ciò significa qualcosa come:

char cmd1[] = "ls";  char *args1[] = {"ls", "-l", NULL};
char cmd1[] = "rm";  char *args1[] = {"rm", "*.txt", NULL}; // but see
// globbing below.
char cmd1[] = "cat"; char *args1[] = {"cat", "makefile", NULL};

Questo è un esercizio non banale, soprattutto se si desidera consentire citazioni, globbing, fughe e così via.

Citando significa che dovrai fare attenzione con comandi come:

rm "file with spaces.txt"

in quanto non puoi semplicemente rompere sugli spazi -Dovrai interpretare gli elementi nel comando più o meno come fa la shell: un'interruzione semplicistica degli spazi ti darebbe un comando con tre argomenti per quella stringa sopra, anziché quella corretta.

Con il globbing, voglio dire che quasi certamente avrai problemi con qualcosa di simile *.txt poiché è tipicamente il conchiglia che espande questi argomenti. Passando direttamente a execvp() risulterà in a singolo argomento di letteralmente *.txt piuttosto che molti argomenti che corrispondono a tutti i file di testo nella tua directory corrente.

Citando significa che dovrai gestire cose come:

ls -l "file with spaces and " quote in it"

che complicherà ulteriormente il parser.

Non fraintendetemi, si può fare, ma probabilmente è più dannatamente semplice da usare system().

Se stai ancora pensando di andare al execvp() percorso, dovrai:

  • dividi la stringa in token separati (piuttosto difficile, dato che devi gestire preventivi e fughe).
  • glob tutti gli argomenti, nel senso che quelli con caratteri jolly in essi (e solo quelli che non sono salvati o protetti in virtù di essere all'interno di virgolette) vengono espansi in più argomenti.
  • costruire l'array di argomenti, con il comando nella parte anteriore e un NULL alla fine.
  • chiamata execvp() con i parametri come primo elemento in quell'array e l'indirizzo dell'array.

2 per risposta № 2

No, il exec famiglia di funzioni non accetta una singola riga di comando come system lo fa. Invece usa un argv-come array di stringhe:

char *command = "/path/to/command";
char *arguments[] = { "command", "first argument", "second argument", NULL };
execvp(command, arguments);

Si noti che la prima voce in arguments array è il comando stesso e la matrice viene terminata da NULL.

Hai controllato la pagina del manuale?


2 per risposta № 3

Per usare una qualsiasi delle funzioni in stile execve, lo faraiè necessario analizzare la riga di comando e creare un vettore argv. Le funzioni prendono un carattere **, in cui l'ultimo elemento è nullo: sarà necessario allocare memoria sufficiente per tutto questo, quindi la chiamata in stile execve dovrebbe funzionare.

(p.s. Non hai mai parlato di fork ...)


1 per risposta № 4

Per fare in modo che funzioni come "*" ">", "<", "&" ecc., È necessario eseguire "/ bin / sh" e passare la riga di comando come argomenti. Quindi, si tratta di tokenizzare la stringa.


1 per risposta № 5

Quello che devi fare qui è fare in modo che la shell analizzi il comando. Quindi considera questo:

/bin/sh -c "rm *.txt"

Questo dovrebbe farti andare nella giusta direzione. :)