Search code examples
linuxg++system-callsexecv

execv system call not running as desired


I use Linux and while compiling any c or cpp file, I use gcc or g++ respectively in terminal. Common syntax : g++ program.cpp

But now I wish to compile files using flags. Eg: g++ -Wall -Wextra -std=c++11 program.cpp I will use more 10 flags to compile my program. But I don't want to remember and type that while compiling in terminal.

Now I wish to create a c program involving syscalls (exec) to get my job done using below syntax: ./compile program.cpp

But there's some problem while using exec in my below code

#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
int main(int args, char* argv[]){
    char* arguments[10]={"-std=c++11","-Wall","-Wextra","-pedantic","-Wshadow","-fsanitize=address","-fsanitize=undefined","-fstack-protector"}; //consists of flags with which i will compile the program passed as argument
    printf("%s\t %s",argv[0],argv[1]);
    if(args==2){
        arguments[8]=argv[1];
        arguments[9]=(char*)NULL;
    }else{
        printf("only one argument allowed!");// just to check if i pass arguments correctly
    }
    printf("%s\t %s",arguments[8],arguments[9]);// just to check if my arguments array is correct
    if(execv("/bin/g++",arguments)==-1){ // to my suprise this line runs before above printing lines. What is the reason/solution?
        perror("execv failed!");
        exit(1);
    }
    
    return 0;
}

The above code compiles successfully without error. But I think execv runs even before I insert passed argument in argument array. Because of which, program runs with error execv failed: no such file or directory Followed by the printfs. Please tell me where I went wrong.


Solution

  • So I finally solved the ambiguity in the above code. I made two radical changes to my code.

    1. Instead of directly assigning argument strings while declaration of string array,
    char* arguments[10]={"-std=c++11","-Wall","-Wextra","-pedantic","-Wshadow","-fsanitize=address","-fsanitize=undefined","-fstack-protector"};
    

    I chose to just assign strings one by one.

    char* arguments[10];
            arguments[0]="g++";
            arguments[1]="-Wall";
            arguments[2]="-Wextra";
    and so on
    

    And this fixed the segmentation faults in my code.

    1. This time I used execvp() instead of execv() system call because of which I don't need to explicitly declare full path to the command usr/bin/g++ and so on. In execvp only command name is enough. So my new code looks like this:
    #include<stdio.h>
    //#include<fcntl.h>
    #include<unistd.h>
    #include<stdlib.h>
    int main(int args, char* argv[]){
            char* arguments[10];
            //printf("%s\t %s\n",argv[0],argv[1]); 
            arguments[0]="g++";
            arguments[1]="-Wall";
            arguments[2]="-Wextra";
            arguments[3]="-pedantic";
            arguments[4]="-Wshadow";
            arguments[5]="-fsanitize=address";
            arguments[6]="-fsanitize=undefined";
            arguments[7]="-fstack-protector";// to add more flags make changes in this array.
            if(args==2){
                    arguments[8]=argv[1];
                    arguments[9]=(char*)NULL;
                    if(execvp(arguments[0],arguments)==-1){
                            perror("execv failed!");
                            exit(1);
                    }
    
            }else{
                    printf("->Only one argument(c/cpp file) allowed.\n->Requtired syntax: ./compile program.cpp\n");
            }
            return 0;
    }
    
    1. Another question I had was that all printfs that were before execv() system call would get printed only after execv() got executed. And as @MYousefi Sir commented, it was because of buffer not being full. And as suggested, adding "\n" in printfs solved the problem.