Search code examples
cexecl

execl() works on one of my code, but doesn't work on another


I already used execl() in code, and it worked well.

But this time, I really have no idea why it doesn't work.

So here's the code that do not work

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

int main()
{
     int i = 896;

     printf("please\n");
     execl("home/ubuntu/server/LC/admin/admin", (char*)i, NULL);
     printf("i have no idea why\n");

     return 0;
}

And here's the admin.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
     int mid = argv[0];

     printf("hi from child\n");
     printf("%d\n", mid);
     return 0;
}

Of course I compiled admin.c to admin, and the path isn't wrong.

>ls
admin admin.c why why.c
>pwd
/home/ubuntu/server/LC/admin
>./admin
hi from child
-1180858374
>./why
please
i have no ida why

Anyone know why it doesn't work?


Solution

  • My C is a bit rusty but your code made many rookie mistakes.

    1. execl will replace the current process if it succeeds. So the last line ("i have no idea why") won't print if the child can launch successfully. Which means...

    2. execl failed and you didn't check for it! Hint: check the typecast to char *.

    3. You cast an int to a char * in the execl call, then again when you launch the child (admin). This is a big no-no in C. It freely allows you to misinterpret types. The only warning is most often a crash. GGC will warn you about it. I don't know about the compiler on AWS.

    4. Check your array's bound! You don't know how many parameters admin was launched with. argv[0] always exist because it contains a representation of the program name. argv[1] may not be defined. Accessing array out-of-bound is an undefined behavior and highly dangerous.

    The standard way to start another process in C is to fork the parent, then call one of the functions in the exec family to start the other process.

    Consider this instead (I took the liberty to emit different messages to make them clearer).

    parent.c

    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    
    int main()
    {
        int i = 896;
        char str[15];
        int pid;
    
        printf("Hello from parent\n");
        sprintf(str, "%d", i); // convert the number into string
    
        pid = fork();
        if (pid == -1)
        {
            printf("Fork failed\n");
        }
        else if (pid == 0)
        {
            printf("Continue from parent\n");
        }
        else
        {
            // start the child process
            execl("home/ubuntu/server/LC/admin/admin", str, NULL);
    
            // check if it started properly
            if (errno != 0)
            {
                printf("Error launching child process: %s\n", strerror(errno));
                return 1;
            }
        }
    
        printf("Goodbye from parent\n");    
        return 0;
    }
    

    admin.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/msg.h>
    #include <string.h>
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
        char * mid;
    
        // argc is always 1 or more
        if (argc >= 2)
            mid = argv[1];
        else
            mid = "<nothing>";
    
        printf("hello from child\n");
        printf("argc = %d, argv[1] = %s\n", argc, mid);
        return 0;
    }