mehmet
mehmet

Reputation: 65

system() call or exec() functions not working when i send command with char array in c language

I am trying to make video looper in linux. For that i am using mplayer for videos. My program gets list of videos and images from directory and plays them. My problem is when i call mplayer or image viewer from c with char array parameters it is not working. For example,

system("eog -f /home/user/Desktop/Video/screenshot_0000.png");

or

system("mplayer -fs /home/user/Desktop/Video/video1.mov");

if i call this way it works. But when i get video list from directy and send them with char array it is not working. When i tried system() call it gives 'sh: 1: video1.mov not found' error and when i use exec() fuctions nothing happens.

Here is my code;

    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/wait.h>
    #include <dirent.h>
    #include <string.h>

    #define FILE_PATH "/home/user/Desktop/Video/"

    char *getExt (const char *fspec) {
        char *e = strrchr (fspec, '.');
        if (e == NULL)
            e = ""; // fast method, could also use &(fspec[strlen(fspec)]).
        return e;
    }

    void get_list(char liste[][150])
    {
        DIR *d;
        struct dirent *dir;
        char *path = ("%s.",FILE_PATH);
        d = opendir(path);
        int counter=0;
        /*if(d != NULL)
        {
            while((dir=readdir(d))!= NULL)
            {
    //          printf("%s\n", dir->d_name);
                if(dir->d_type==DT_REG)
                    file_numbers++;
            }
            closedir(d);

        }
        char liste[file_numbers][150];*/
        d = opendir(path);
        if(d != NULL)
        {
            while((dir=readdir(d))!= NULL)
            {
    //          printf("%s\n", dir->d_name);
                if(dir->d_type==DT_REG)
                {   
                    strncpy(liste[counter],dir->d_name,150);
    //              printf("%s\n", liste[counter]);
                    counter++;
                }
            }
            closedir(d);

        }

    }

    int main ()
    {
        int status;
        pid_t child_pid, pid_w;
        DIR *d;
        struct dirent *dir;
        char *path = ("%s.",FILE_PATH);
        d = opendir(path);
        int file_numbers=0;
        int counter = 0;
        if(d != NULL)
        {
            while((dir=readdir(d))!= NULL)
            {
    //          printf("%s\n", dir->d_name);
                if(dir->d_type==DT_REG)
                    file_numbers++;
            }
            closedir(d);

        }
        char liste[file_numbers][150];
        get_list(liste);
        /*for(int i = 0; i< file_numbers;i++)
            printf("%s\n", liste[i]);*/

        while(1)
        {
            char *ext = getExt(liste[counter]); 
            //printf("eog -f %s/%s\n",PATH,liste[counter]);
            child_pid = fork();
            if(child_pid==0)
            {
                //printf("-eog -f %s/%s\n",PATH,liste[counter]);
                if(!strcmp(ext,".JPG") || !strcmp(ext,".jpg") || !strcmp(ext, ".gif") || !strcmp(ext,".png") || !strcmp(ext, ".PNG") || !strcmp(ext, ".GIF"))
                {   
                    //printf("eog -f %s%s\n",FILE_PATH,liste[counter]);
                    char command[1000];
                    strcpy(command,("eog -f %s%s",FILE_PATH,liste[counter]));
                    //printf("%s", command);
                    execl(command,command,NULL,NULL);
                    sleep(5);
                }           
                else if (!strcmp(ext,".mov") || !strcmp(ext, ".mp4") || !strcmp(ext, ".avi") || !strcmp(ext,".wmv"))
                {
                    //printf("mplayer -fs %s%s\n",FILE_PATH,liste[counter]);
                    char command[1000];
                    strcpy(command,("mplayer -fs %s%s",FILE_PATH,liste[counter]));
                    //printf("%s",command);
                    execl(command,command,NULL,NULL);
//                  system(command);

                }
                else 
                    printf("--%s%s",FILE_PATH,liste[counter]);      
            }
            else
            {
                pid_w = waitpid(child_pid,&status,0);
    //          system("eog -f /home/user/Desktop/Video/screenshot_0000.png");
    //                  sleep(5);
    //                  exit(EXIT_SUCCESS);
            }
            counter++;
            if(counter >=file_numbers)
                counter =0;

        }
    }

Upvotes: 0

Views: 242

Answers (2)

user3629249
user3629249

Reputation: 16540

calls to fork() can result in three different return states.

  1. currently executing the parent process and the returned value is the PID of the child process
  2. currently executing the child process and the returned value is 0
  3. no process was created, the returned value is -1

The posted code is failing to handle #3.

Suggest:

 child_pid = fork();
 switch( child_pid )
 {
     case 0:  // child
         ....
     break;

     case -1: // error
         perror( "fork failed" );
         exit( EXIT_FAILURE );
         break;

     default:  // parent
         pid_w = waitpid(child_pid,&status,0); 
         break;
 } // end switch()

calls to execl() need the following parameters:

  1. const char *path to the executable
  2. const char *first executable argument
  3. const char *second executable argument
  4. ....
  5. NULL

since you want to execute :`

eog -f %s%s",FILE_PATH,liste[counter]));

the call to execl() should look similar to:

char buffer[1024];
sprintf( "%s%s", FILE_PATH, liste[counter] );
execl( "eog", "eog", "-f", buffer, NULL );
// the 'execl()' function does not return 
// unless there was an error so:
perror( "execl failed" );
exit( EXIT_FAILURE );      // this exits child process when failure occurred

Upvotes: 0

user2371524
user2371524

Reputation:

I'm not sure it's the only error, but it's the one that's obviously your immediate problem:

strcpy(command,("mplayer -fs %s%s",FILE_PATH,liste[counter]));

I don't know how you got the idea this would somehow format a string. What it does is to copy liste[counter] to command. The reason is that the second argument to your strcpy is a paranthesized expression:

("mplayer -fs %s%s",FILE_PATH,liste[counter])

It uses the comma operator (,) twice. The comma operator does the following:

1.) it evaluates both sides of the comma sequenced (first the left hand side, then the right hand side) 2.) its evaluation result is that of the right hand side, the other result is just discarded (*)

So, here

"mplayer -fs %s%s",FILE_PATH,liste[counter]

is exactly equivalent to just

liste[counter]

What you're looking for is snprintf():

snprintf(command, sizeof(command), "mplayer -fs %s%s", FILE_PATH, liste[counter]);

This will do what you obviously expected. On a side note, also observe how putting a blank after each comma makes this whole line a lot more readable, so I'd recommend you do the same.


(*) but the order of side effects is well-defined, that's what it's used for -- of course, here you don't have any side effects

Upvotes: 2

Related Questions