2

I have to make a custom shell as a school project and I'm hitting a wall with this:

int exec_shell(char **argv) //
{
    if (execve(argv[0], (char **)argv , NULL)==-1) //if an error occurs
    {
            printf("Commande invalide : %s\n", argv[0]);
            fflush(stdout);//vide le buffer
            exit(0);
            return -1;
    }

    return 0;
}

It's supposed to be very simple - you put in a command in string form and exec calls the said command. However, it always returns an error.

What am I doing wrong?

Here is the single warning:

primitives.c:25:30: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

Pang
  • 9,564
  • 146
  • 81
  • 122
Jib
  • 45
  • 1
  • 5
  • 2
    What is line 25 of your code? That's where the warning is coming from. – FKEinternet Jun 20 '17 at 03:38
  • 1
    The `(char **)` cast is pointless given the `char **argv` argument. Don't use unnecessary casts. What's in `argv[0]`? You're not supposed to pass a null pointer as the environment argument. Processes are entitled to a minimal environment — and you should pass a valid pointer to an empty list rather than a null pointer (`char *empty[] = { 0 };` and pass `empty` in place of `NULL`). If you checked `errno` (or used `perror()` before calling `printf()`) you would like see `EINVAL` or `Invalid argument` as the error condition. Also, errors should normally be reported on `stderr`, not `stdout`. – Jonathan Leffler Jun 20 '17 at 04:02
  • Please read this specification for execve api. https://linux.die.net/man/2/execve – Kanji Viroja Jun 20 '17 at 04:28
  • Here is an example I wrote using `execvp()`: https://stackoverflow.com/a/42973015/900078 – pynexj Jun 20 '17 at 04:33
  • Are you sure you are using a C compiler, somehow this warning smells like C++. – alk Jun 20 '17 at 04:51
  • [RESOLVED] Hey, I would like to thank you all for your answer. It helped me figure out better what was wrong and I found an answer here https://stackoverflow.com/questions/10158782/execve-no-such-file-or-directory – Jib Jun 20 '17 at 20:25

3 Answers3

0

Step : 1

/* myecho.c */

#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
   int j;

   for (j = 0; j < argc; j++)
       printf("argv[%d]: %s\n", j, argv[j]);

   exit(EXIT_SUCCESS);
}

Compile Program : gcc myecho.c -o myecho

step : 2

/* execve.c */

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

int
main(int argc, char *argv[])
{
   char *newargv[] = { NULL, "hello", "world", NULL };
   char *newenviron[] = { NULL };

   if (argc != 2) {
       fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
       exit(EXIT_FAILURE);
   }

   newargv[0] = argv[1];

   if (execve(argv[1], newargv , newenviron) == -1) //if an error occurs
    {
            printf("Commande invalide : %s\n", argv[0]);
            fflush(stdout);//vide le buffer
            exit(0);
            return -1;
    }
}

compile program : gcc execve.c -o execve

step: 3 //Final call

./execve ./myecho

step: observe output.

Kanji Viroja
  • 493
  • 1
  • 7
  • 17
0

To pass an empty environment either define and pass

char * env[] = { NULL };

as third parameter to execve() like this

execve(argv[0], argv, env)

or use a compound literal by doing

execve(argv[0], argv, (char*[]){NULL})

Also the members of the exec*() family of functions only return on error, so the surrounding code might look like this:

int main(void)
{

  ...

  execve(argv[0], argv, (char*[]){NULL});
  perror("execve() failed");

  return EXIT_FAILURE; /* include stdlib.h to have this macro available */
}
alk
  • 69,737
  • 10
  • 105
  • 255
0

[RESOLVED] Hey, I would like to thank you all for your answer. It helped me figure out better what was wrong and I found an answer here. The main issue was the path not being correct.

Jib
  • 45
  • 1
  • 5