Création d'un Shell (Execve et arguments)

Création d'un Shell (Execve et arguments) - C - Programmation

Marsh Posté le 16-02-2009 à 21:24:06    

Bonjour,
Je code actuellement un Shell, et je rencontre un problème avec la commande execve qui permet l'exécution de la commande rentré dans le shell.
 
un bout de code :

Code :
  1. int     main()
  2. {
  3.   extern char   **environ;
  4.   char          **str;
  5.   while (42)
  6.     {
  7.       my_putstr("$Mon_shell_aime_les_asteks>" );
  8.       str = my_str_to_wordtab(get_next_line(0));
  9.       if (fork() == 0)
  10.         execve("/bin/", str, environ);
  11.       wait(NULL);
  12.     }
  13. return (0);
  14. }


 
J'ai mis en dur le path bien que plus tard je compte le placé dans une boucle ;)
lorsque get_next_line = ls, je dois pouvoir afficher ls ;)
en revanche la commande passe très bien si je passe "/bin/ls".
Un bout du man (en Anglais ;))
 

Spoiler :


NAME
     execve -- execute a file
 
LIBRARY
     Standard C Library (libc, -lc)
 
SYNOPSIS
     #include <unistd.h>
 
     int
     execve(const char *path, char *const argv[], char *const envp[]);
 
DESCRIPTION
     The execve() system call transforms the calling process into a new
     process.  The new process is constructed from an ordinary file, whose
     name is pointed to by path, called the new process file.  This file is
     either an executable object file, or a file of data for an interpreter.
     An executable object file consists of an identifying header, followed by
     pages of data representing the initial program (text) and initialized
     data pages.  Additional pages may be specified by the header to be ini-
     tialized with zero data; see elf(5) and a.out(5).
 
     An interpreter file begins with a line of the form:
 
           #! interpreter [arg]
 
 
     When a program is executed as a result of an execve() system call, it is
     entered as follows:
 
           main(argc, argv, envp)
           int argc;
           char **argv, **envp;
 
     where argc is the number of elements in argv (the ``arg count'') and argv
     points to the array of character pointers to the arguments themselves.
 
RETURN VALUES
     As the execve() system call overlays the current process image with a new
     process image the successful call has no process to return to.  If
     execve() does return to the calling process an error has occurred; the
     return value will be -1 and the global variable errno is set to indicate
     the error.
 
CAVEAT
     If a program is setuid to a non-super-user, but is executed when the real
     uid is ``root'', then the program has some of the powers of a super-user
     as well.
 
SEE ALSO
     ktrace(1), _exit(2), fork(2), execl(3), exit(3), sysctl(3), a.out(5),
     elf(5), environ(7), mount(8)
 
STANDARDS
     The execve() system call conforms to IEEE Std 1003.1-2001 (``POSIX.1''),
     with the exception of reopening descriptors 0, 1, and/or 2 in certain
     circumstances.  A future update of the Standard is expected to require
     this behavior, and it may become the default for non-privileged processes
     as well.  The support for executing interpreted programs is an extension.
 
HISTORY
     The execve() system call appeared in 4.2BSD.
 


 
Merci a tous ceux qui m'apporteront leur aide ;)
 
Leoz


---------------
Worldcraze 10loop
Reply

Marsh Posté le 16-02-2009 à 21:24:06   

Reply

Marsh Posté le 16-02-2009 à 21:46:16    

Contenu de "str" ? Code retour + errno de execve() ?
Et tu parles d'un "problème rencontré",  mais lequel au juste ?

 

Parce que là on ne peut pas grand chose pour t'aider, surtout avec des fonctions dont tu ne donnes pas le code.


Message édité par Elmoricq le 16-02-2009 à 21:46:56
Reply

Marsh Posté le 16-02-2009 à 21:55:20    

Pardon ^^
str est égale a my_str_to_wordtab qui est une fonction qui coupe une chaine de caractère mot a mot afin de les placer dans un tableau en gros :
"coucou ça va ?" est égale a  
tab[0] = coucou
tab[1] = ça
tab[2] = va
tab[3] = ?
tab[4] = 0
 
Le problème rencontré est le fait que str = ls (normalement ^^) et execve doit executer ls grace au path ("/bin/" ) passez ;)
 
Execve n'execute jamais ls... a part si je passe en path = "/bin/ls" et dans ce cas execve effectue ls a chaque appelle de celui-ci.
 
Comment dire a execve que str = ls et que path = "/bin/" et après l'exécution il effectue "/bin/ls" ;)
 
Merci :)


---------------
Worldcraze 10loop
Reply

Marsh Posté le 16-02-2009 à 22:17:01    

J'avais même pas vu que tu faisais ça.

 

Ta manpage n'est sans doute pas très explicite, je te colle le bout de la mienne qui t'intéresse, parce que c'est très fourbe en fait execv, à cause de la manière dont argv doit être constitué et qui peut préter à confusion :

Citation :

    The path argument pointsto a path name that identifies the
     new process image file.

 

    The argv argument is  an  array  of  character  pointers  to
     null-terminated  strings. The last member of this array must
     be a null pointer. These  strings  constitute  the  argument
     list  available  to  the  new  process  image.  The value in
     argv[0] should point to a filename that is  associated  with
     the process being started by one of the exec functions
.

 

De plus, il est bon de gérer les erreurs.

 

Ainsi :

$ cat foobar.c
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

 

int main(int argc, char **argv, char **envp) {
   char *foo[] = { "ls", NULL };

 

  int ret = execve("/bin", foo, envp);

 

  if (ret == -1 )
      perror("Plantated" );

 

  return 0;
}

 

$ cc foobar.c

 

$ a.out
Plantated: Permission denied

 

Ce qui rend les choses plus explicites (le programme tente d'exécuter "/bin" ).

 

En somme : le premier argument c'est l'objet à exécuter.

 

Le second argument "argv" contient la liste des arguments à lui passer, avec argv[0] == le nom de l'objet exécuté (ou assimilé), comme ce que tu obtiens dans argv[0] en utilisant ce prototype de main() : "int main(int argc, char **argv)".

 

Et le dernier contient les variables d'environnement.

 

Et donc (juste un exemple sans fork() ni rien) :

Code :
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <errno.h>
  4.  
  5. int main(int argc, char **argv, char **envp) {
  6.   char *foo[] = { "/bin/ls", "-l", NULL };
  7.  
  8.   int ret = execve(foo[0], foo, envp);
  9.  
  10.   if (ret == -1 )
  11.      perror("Plantated:" );
  12.  
  13.    return 0;
  14. }
 

$ cc foobar.c

 

$ a.out
total 3856
-rw-r--r--   1 scottinet cmidev      6578 Jan 28 16:45 CVS.zip
drwxr-xr-x   6 scottinet cmidev      8192 Jan 23 14:18 EC
-rw-r--r--   1 scottinet cmidev     29337 Jan  8 14:17 ECTrade.cc
etc.


Message édité par Elmoricq le 16-02-2009 à 22:20:51
Reply

Marsh Posté le 16-02-2009 à 23:10:01    

N'oublie pas la gestion des pipes :D

Reply

Marsh Posté le 17-02-2009 à 18:41:45    

Merci a vous.
J'ai tout RM, je recommence mon projet a 0 ;)
J'aurais sans doute d'autre question donc je laisse ouvert le topic ;)
 
Leoz


---------------
Worldcraze 10loop
Reply

Marsh Posté le 25-02-2009 à 20:47:14    

bonjour
 
moi aussi je souhaite faire a peu pres la meme chose, mais je ne trouve pas.
 
Je voudrais a partir d'un programme en C, lancer un fichier php  
comme en ssh ou en cron, je fais : php /var/www/test.php
 
savez vous comment faut faire ?
 
Merci

Reply

Marsh Posté le 25-02-2009 à 23:11:54    

man system

Reply

Marsh Posté le 27-02-2009 à 13:55:15    

Ou bien fork()/execl(), qui est un poil plus compliqué mais qui évite de lancer un shell pour rien.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed