3

Program : List all C files in the current folder using execlp() system call:

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

int main()
{
    printf("Before Execl\n");
    execlp("ls","ls","*.c",NULL); // this should print all c files in the current folder.
    return 0;
}

Program output:

Before Execl
ls: cannot access *.c: No such file or directory

Whenever I use '*' in the search pattern, I am getting a similar kind of error. Please suggest some appropriate solution.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Kunal
  • 597
  • 7
  • 19

4 Answers4

2

If you want shell metacharacters expanded, invoke the shell to expand them, thus:

execlp("sh", "sh", "-c", "ls *.c", (char *)0);
fprintf(stderr, "Failed to exec /bin/sh (%d %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);

Note that if execl() or any of the exec* functions returned, it failed. You don't need to test its status; it failed. You should not then do exit(0); (or return 0; in the main() function) as that indicates success. It is courteous to include an error message outlining what went wrong, and the message should be written to stderr, not stdout — as shown.

You can do the metacharacter expansion yourself; there are functions in the POSIX library to assist (such as glob()). But it is a whole heap simpler to let the shell do it.

(I've revised the code above to use execlp() to conform to the requirements of the question. If I were doing this unconstrained, I'd probably use execl() and specify "/bin/sh" as the first argument instead.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Note that if you forked before calling `execlp`, any use of `stdio` operations in the child is probably wrong, unless you're sure that (1) the program is single-threaded, and (2) the child's copy of `stderr` (or whichever `FILE` you are using) is qualified to become the "active handle" (see POSIX XSH 2.5.1). Personally I would just avoid any use of non-async-signal-safe functions following `fork`, which also includes `exit`; use `_Exit` instead. – R.. GitHub STOP HELPING ICE Mar 09 '12 at 07:40
  • That [XSH §2.5.1](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05) is a complicated way of saying "If you program normally, you will be OK". In particular, `stderr` is normally unbuffered, and gets the "no action need be taken" OK on the third bullet. – Jonathan Leffler Mar 09 '12 at 15:02
  • Well being normally unbuffered is an implementation detail. As I recall, the standards just say that it shouldn't be fully buffered by default, so having `stderr` line buffered by default is probably conformant for an implementation and might give significantly better performance. I would call `fflush(stderr)` before forking if you intend to use it in both parent and child after the fork, just to be safe... – R.. GitHub STOP HELPING ICE Mar 09 '12 at 16:48
0

Exec does not handle the "*" operator as the shell does it for you. Use popen() or glob_t for this. You can get more details on a similar question which I asked on 2012-03-08.

Community
  • 1
  • 1
sragvuw
  • 33
  • 5
  • Why `popen()`? You aren't about to write to the `ls` command, or read its output, so why would you benefit from a pipe? The `glob_t` you mention is a type associated with the [`glob()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/glob.html) function. – Jonathan Leffler Mar 09 '12 at 06:24
-1

Should it be:

   execlp("ls", "*.c", NULL);
Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
-1
execlp("ls", "*.c", NULL);

should work

Amod
  • 1