2

I am trying to send arguments(e.g:ls,date,cal) to a new shell ,execute those arguments and terminate.

  #include"header.h"  //includes all the header files

 int main(int argc,char * argv[],char *envp[]) {
     char *ap[]={"sh","ls",NULL};
     int p=execve("/bin/sh",ap,envp);
     printf("error:%d",p);

     perror("execve");

 }

output:

sh:0:can't open ls
dlmeetei
  • 9,905
  • 3
  • 31
  • 38
  • Header.c is a user defined one which includes all the necessary library files – Totla Sathish Sep 22 '17 at 12:49
  • what about `char *ap[]={"ls",NULL};` – Jean-François Fabre Sep 22 '17 at 12:50
  • 2
    I'm not 100% sure I understand what you are trying to do, but I think that should be `{"sh", "-c", "ls", 0}`. `-c` means "the next argument is a command"; without it, the first non-option argument to `sh` is interpreted as the name of a shell script to invoke. – zwol Sep 22 '17 at 12:50

1 Answers1

4

This has nothing to do with execve. Your program correctly invokes sh ls.

It's just that sh interprets its first argument as the name of a shell script to run, but there is no file called ls in the current directory, hence the error. You'd get the same results by running sh ls manually.

If all you want to do is run ls, why go through the shell at all? Just do:

char *ap[]={"ls",NULL};
int p=execve("/usr/bin/ls",ap,envp);

On the other hand, if you want to use the shell, you need to tell it that its argument is supposed to be a command, not the name of a file. You do that with sh -c ls:

char *ap[]={"sh","-c","ls",NULL};
melpomene
  • 84,125
  • 8
  • 85
  • 148
  • 2
    Or `execlp("ls", "ls", (char *)0)` to get path searching. (Note: that `char *` cast is necessary, _even if_ you prefer to write null pointers as NULL.) – zwol Sep 22 '17 at 12:54
  • thanks for your help – Totla Sathish Sep 22 '17 at 13:04
  • @zwol Ah yes, cast needed because of the `...` of `int execlp(const char *file, const char *arg, ...);` – chux - Reinstate Monica Sep 22 '17 at 15:36
  • @zwol I always do `(char *)NULL`, but I think the cast is technically not required on platforms that define `NULL` as `((void *)0)`. – melpomene Sep 22 '17 at 18:52
  • @melpomene No, it's required even if that is the definition of NULL, because `void *` and `char *` are not required to be passed the same way through a variable argument list. (I have a vague memory that C11 changed that but I don't remember for sure, and anyway it's about 15 years too soon to be assuming C11.) – zwol Sep 22 '17 at 19:36
  • @zwol Ah, great fun. – melpomene Sep 22 '17 at 19:38