3

I am new to system calls and C programming and am working on my university assignment.

I want to call the 'ls' command and have it print the directory.

What I have: (I have added comments in so you can see what I see coming through each variable.

int execute( command* cmd ){

  char full_path[50];
  find_fullP(full_path, p_cmd); 
  //find_fullP successfully updates full_path to /bin/ls
  char* args[p_cmd->argc];
  args[0] = p_cmd->name;
  int i;
  for(i = 1; i < p_cmd->argc; i++){
      args[i] = p_cmd->argv[i];
  }

/*
 * this piece of code updates an args variable which holds arguments 
 * (stored in the struct) in case the command is something else that takes 
 * arguments. In this case, it will hold nothing since the command 
 * will be just 'ls'.
 */

  int child_process_status;
  pid_t child_pid;
  pid_t pid;

  child_pid = fork();

  if ( child_pid == 0 ) {
      execv( full_path, args );
      perror("fork child process error condition!" );
  }

  pid = wait( &child_process_status );
  return 0;
}

I am not seeing anything happening and am confused, any idea?

ilent2
  • 5,171
  • 3
  • 21
  • 30
asdf
  • 657
  • 1
  • 13
  • 30
  • 1
    Use `opendir`, `readdir`, and `closedir` instead of using an external program – Ed Heal Feb 13 '15 at 20:13
  • 1
    Add logging (just printing stuff is fine) to find out how far you get and whether variables hold the values you think they hold. Or use a debugger. – David Schwartz Feb 13 '15 at 20:16
  • @EdHeal Do you think that will get full marks when submitted as the university assignment? – Kaz Feb 13 '15 at 20:17
  • 1
    Your `args` array should terminate with `NULL`. See `man execv` – Eugene Sh. Feb 13 '15 at 20:17
  • 1
    If the assignment is to print a directory, I would expect it to get higher marks. – David Schwartz Feb 13 '15 at 20:17
  • 2
    Why don't you change the representation of `p_cmd->argv[]` so that `p->cmd_argv[0]` is the program name? Then you don't have to make a copy. You can just use that `argv` object. Don't forget that `argv[argc]` must be a null pointer. The argv for a program with N arguments requires N+2 elements. One for the program name, N for the arguments, and one for the null pointer which terminates the array. If you don't terminate the array, then `/bin/ls` may find a complete garbage pointer in `argv[1]` (so `ls` crashes), or a pointer to junk data (which looks like a file which it cannot find). – Kaz Feb 13 '15 at 20:18
  • I added NULL to the end of args and it worked, but now I get an "Abort Trap: 6" error. – user3037172 Feb 13 '15 at 20:21
  • Using an external program uses fewer system calls. Therefore the use of `opendir` etc would get better marks. (also more efficient) – Ed Heal Feb 13 '15 at 20:22
  • Make sure that you have allocated the space for the NULL element. – Eugene Sh. Feb 13 '15 at 20:22
  • @EdHeal For just printing the directory contents, it's much simpler to use `ls` than messing with own lower level implementation, really. – Eugene Sh. Feb 13 '15 at 20:26
  • No is not. about 5 lines of code and a format of your choosing. Without the assumption `/bin/ls` or it printing in the desired format – Ed Heal Feb 13 '15 at 20:29
  • @user3037172 did you edit the post as another user? – Iharob Al Asimi Feb 13 '15 at 20:34
  • Perhaps http://stackoverflow.com/questions/3554120/open-directory-using-c is worth a read – Ed Heal Feb 13 '15 at 20:47

1 Answers1

14

Here's the minimal program that invokes ls using execv. Things to note

  • the list of args should include the executable as the first arg
  • the list of args must be NULL terminated
  • if the args are set up correctly, then args[0] can be passed as the first parameter to execv

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main( void )
{
    int status;
    char *args[2];

    args[0] = "/bin/ls";        // first arg is the full path to the executable
    args[1] = NULL;             // list of args must be NULL terminated

    if ( fork() == 0 )
        execv( args[0], args ); // child: call execv with the path and the args
    else
        wait( &status );        // parent: wait for the child (not really necessary)

    return 0;
}
gsamaras
  • 71,951
  • 46
  • 188
  • 305
user3386109
  • 34,287
  • 7
  • 49
  • 68