Hi ha diferents funcions de C per executar aplicacions/comandes. Totes comencen per exec però només hi ha una crida de sistema: execve. Totes les funciones exec acaben fent ús d'aquesta crida de sistema.
IMPORTANT: Les crides exec no creen nous processos! Només substitueixen en procés que les executa per un altre programa. El "nou procés" té el mateix PID que el procés que ha executat exec.
C utilitza les funcions :
#include <unistd.h> extern char **environ; int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg,..., char * const envp[]); int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]);
La crida de sistema de UNIX és:
Crida al sistema:
#include <unistd.h> int execve(const char *filename, char *const argv[],char *const envp[]);
Per tal d'executar comandes i aplicacions. No s'ha de confondre aquestes funcions de C amb la crida de sistema execve. Els altres sufixos volen dir:
Les diferències entre execv i execl estan en que execl utilitza una llista de paràmetres indefinits a priori per especificar els paràmetres de la comanda que volem executar i execv utilitza un vector.
Consulteu | execve a l'article Crides_al_sistema_de_Unix#Execuci.C3.B3_de_programes._Exec.
#include <unistd.h> main() { execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0); }
Execlp és equivalent a execl però si el path a la comanda no conté el caràcter / aleshores es buscarà la comanda a el PATH del sistema (variable d'entorn PATH). La variable d'entorn PATH es pot consultar amb:
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
o
$ env | grep PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
Si el PATH no està especificat s'utilitza el PATH per defecte:
:/bin:/usr/bin
Executar una comanda:
$ comanda
En C i amb la funció execpl seria:
execlp(“comanda”, “comanda”, NULL);
Executar una comanda amb paràmetres:
$ ls -l fitxer.txt
En C i amb la funció execpl seria:
execlp(“ls”, “ls”, “-l”, “fitxer.txt”, NULL);
Cada Shell té unes variables d'entorn que poden influir sobre l'execució de les comandes. Les variables d'entorn es poden consultar amb:
$ env SSH_AGENT_PID=6900 GPG_AGENT_INFO=/tmp/seahorse-Ryw485/S.gpg-agent:6900:1 SHELL=/bin/bash DESKTOP_STARTUP_ID= TERM=xterm ...
Un de les variables d'entorn és PATH:
$ env | grep PATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
I per aquesta raó no existeix una funció execlep o execlpe.
Podem establir la variable d'entorn amb:
char *env[] = { "USER=user1", "PATH=/usr/bin:/bin:/opt/bin", (char *) 0 };
#include <unistd.h> main() { char *args[] = {"/bin/ls", "-r", "-t", "-l", (char *) 0 }; execv("/bin/ls", args); }
Exemple 1:
El programa:
#define PROGRAMA_FILL "./SelPri" ... char *fargv[3]; ... fargv[0] = PROGRAMA_FILL; fargv[1] = ./primers; fargv[2] = 0; execve(PROGRAMA_FILL, fargv,0);
És equivalent a executar:
$ ./SelPri ./primers string getErrMsg(int errnum);
Exemple 2:
main() { string envFile("environment_variables.conf"); CReadEnvironmentVariablesFile readEnvFile; char **Env_envp = readEnvFile.ReadFile(envFile); // Command to execute char *Env_argv[] = { "/bin/ls", "-l", "-a", (char *) 0 }; pid_t pID = fork(); if (pID == 0) // child { // This version of exec accepts environment variables. // Function call does not return on success. int execReturn = execve (Env_argv[0], Env_argv, Env_envp); cout << "Failure! execve error code=" << execReturn << endl; cout << getErrMsg(execReturn) << endl; _exit(0); // If exec fails then exit forked process. } else if (pID < 0) // failed to fork { cerr << "Failed to fork" << endl; } else // parent { cout << "Parent Process" << endl; } }
Permet executar comandes del sistema:
#include <stdlib.h>
int system(const char *command);
ATENCIÓ: system("command"); és equivalent a executar:
$ /bin/sh -c command
Utilitza sh i no pas bash.
Recursos:
#include <stdio.h> #include <stdlib.h> main() { system("ls -l"); printf("Command done!"); }
Permet executar una funció al finalitzar un programa:
#include <stdlib.h> int atexit(void (*function)(void));
Exemple extret del manual:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> void bye(void) { printf("That was all, folks\n"); } int main(void) { long a; int i; a = sysconf(_SC_ATEXIT_MAX); printf("ATEXIT_MAX = %ld\n", a); i = atexit(bye); if (i != 0) { fprintf(stderr, "cannot set exit function\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; }
Recursos:
Similar a at_exit però permet passar paràmetres.
#include <stdlib.h> int on_exit(void (*function)(int , void *), void *arg);