0

I'm trying to make a program which invokes the ls and grep system calls using exec. Specifically I have to execute ls > tmp; grep ­-c pattern < tmp in order to count the number of files that fulfill the pattern. As you can see I save the content of ls in tmp file and then I want to use grep to count the files.

Let's supose pattern = txt. I'm trying things like the following code:

char *a = "ls > tmp";
char *b = " -c ";
char *fin = " < tmp";
char *comanda;
if((comanda = malloc(strlen(pattern)+strlen(pattern)+1)) != NULL){
  comanda[0] = '\0';   // ensures the memory is an empty string
  strcat(comanda,b);
  strcat(comanda, pattern);
  strcat(comanda,fin);
} else {
    return -1;
}

ret = execl("/bin/sh","sh","-c",a,NULL);
ret = execl("/bin/sh","sh","-c",comanda, NULL);

But it shows me the following error: ls: cannot access > tmp: No such file or directory. So I don't know how to get the value of grep, because the execl function does not return the value, so how can I achieve the grep value?

2 Answers2

1

To get the output of a command, you need to use a pipe.

Have a look at : Connecting n commands with pipes in a shell?

You could just do:

ls | grep -c pattern

If you just want to get files with a specific pattern in filename you might want to use find

find your_path/ -name "*pattern*" | wc -l

Have a look at Grabbing output from exec to get the output of execl

Here is an example, replace the 4th argument of execl with whatever you want :)

(execl("/bin/sh", "sh", "-c", "ls > tmp; grep -c 'pattern' < tmp", (char *)NULL);)

#include <unistd.h>
#include <string.h>

int main()
{
   int fd[2];
   pipe(fd);

   if (fork() == 0)
   {
      close(fd[0]);

      dup2(fd[1], 1);
      dup2(fd[1], 2);
      close(fd[1]);

      execl("/bin/sh", "sh", "-c", "find your_path -name '*pattern*' | wc -l", (char *)NULL);
   }
   else
   {
      char buffer[1024] = {0};

      close(fd[1]);

      while (read(fd[0], buffer, sizeof(buffer)) != 0)
      {
         write(1, buffer, strlen(buffer));
         memset (buffer, 0, sizeof(buffer));
      }
   }
   return 0;
}
Community
  • 1
  • 1
Eliot B.
  • 162
  • 11
0

You're not allocating the correct amount of space for comanda, because you don't add the sizes of all the variables correctly. So if the size is too small, you'll write outside the array bounds when you do all the strcat, and this will cause undefined behavior.

You don't need the temporary file, you can just pipe from ls to grep. I've also added quotes around the pattern in case it contains special characters.

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

int main() {
    char *a = "ls | grep -c '";
    char *fin = "'";
    char *pattern = "foo";
    char *comanda;
    if((comanda = malloc(strlen(a) + strlen(pattern) + strlen(fin) +1)) != NULL){
        strcpy(comanda,a);
        strcat(comanda,pattern);
        strcat(comanda,fin);
    } else {
        return -1;
    }
    int ret = execl("/bin/sh","sh","-c", comanda, (char*)NULL);
    perror("execl"); // Can only get here if there's an error
}
Barmar
  • 741,623
  • 53
  • 500
  • 612