0

my code is pasted below.

I'm trying to use dup2 to redirect my output to file.

if I use it to redirect it works fine (if I remove the comments), output in file and not on stdout. ex: ls > test , results in ls outputting to test.

the problem is that ls, without the > doesn't output anything. If I leave the comments ls outputs just as it should, albeit with no ability to redirect.

redirect[0] is either < or > or nothing redirect[1] is the path for the file to redirect to

command is is an array of cstrings with the pices of the command commands is as well

example output with code commented

xxxxx@myshell:/home/majors/kingacev/ubuntumap/cop4610/proj1> ls
a.out  myshell.c  myshell.c~
xxxxx@myshell:/home/majors/kingacev/ubuntumap/cop4610/proj1>

with code uncommented

xxxxx@myshell:/home/majors/kingacev/ubuntumap/cop4610/proj1> ls
xxxxx@myshell:/home/majors/kingacev/ubuntumap/cop4610/proj1>


  /*
  if (!strcmp(redirect[0],">")){
    if ((fd = open(redirect[1], O_RDWR | O_CREAT)) != -1)
      dup2(fd, STDOUT_FILENO);
    close(fd);
  }
  */

  if (command[0][0] == '/'){
    int c = execv(command[0], commands);
    if (c != 0){
      printf("ERROR: command does not exist at path specified\n");
      exit(0);
    }
  }
  else if (!execv(path, commands)){
    exit(0);
  }
d0m1n1c
  • 157
  • 4
  • 16
  • What is `redirect` and how is it declared? – Some programmer dude Jan 30 '14 at 14:00
  • char* redirect[2]; [0] has either > or < or notheing and [1] has the path for the file – d0m1n1c Jan 30 '14 at 14:01
  • Oh, and have you tried stepping through the code with a debugger? – Some programmer dude Jan 30 '14 at 14:01
  • You don't need to test what any of the `exec*()` functions returns. If it succeeds, it doesn't return; if it returns, it failed. It is conventional to return a non-zero exit when something fails. You could simply call `execvp()`; it knows how to handle absolute (and relative) paths as well as simple names. – Jonathan Leffler Jan 30 '14 at 14:04
  • yeah, all i could learn from stepping through was that it prints to stdout when the commented block is commented and it prints to nowhere when it's uncomented, unless redirect[0] is a > then it prints to file. – d0m1n1c Jan 30 '14 at 14:06
  • I would rather use execvp, but a part of the assignment is that I need to use execv. – d0m1n1c Jan 30 '14 at 14:08
  • Since the commented out code makes it work, your question title is wrong — dup2() is enabling output to file; in its absence, you're getting nothing. The problem, therefore, is not in the code you've shown, but in the code you've not shown. It is as if you've closed or redirected standard output already, so when the command write to standard output, it does not go to the terminal. Since we can't see the other code, there's no way for us to guess what you've done wrong. – Jonathan Leffler Jan 30 '14 at 14:08
  • example with the code commented. ls -l. list the files to stdout – d0m1n1c Jan 30 '14 at 14:10
  • without the code commented. ls -l. outputs to nowhere – d0m1n1c Jan 30 '14 at 14:10
  • without the code commented ls -l > test.txt. lists the files to test.txt – d0m1n1c Jan 30 '14 at 14:11
  • Please clarify the code/text in the question. You say _if I use it to redirect it works fine (if I remove the comments); the problem is that ls, without the `>` doesn't output anything_. What you're saying in the comments is contradicting that — which makes it hard to know what is and is not working. Incidentally, when one of the `open()` flags is `O_CREAT`, you need three arguments to `open()`. – Jonathan Leffler Jan 30 '14 at 14:14
  • with the block removed it works as it should without the ability to redirect. execv(path, commands) for ls prints to std out. with the block of code uncommented redirect works but printing to stout doesn't. ie ls > test will print to test, while ls won't print. – d0m1n1c Jan 30 '14 at 14:19
  • ill paste my output into the question – d0m1n1c Jan 30 '14 at 14:19

1 Answers1

0

This code works, redirecting to file.out:

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

int main(void)
{
    int fd;
    char *redirect[] = { ">", "file.out" };
    char *command[] = { "/bin/ls", "-l", 0 };

    if (!strcmp(redirect[0], ">"))
    {
        if ((fd = open(redirect[1], O_WRONLY | O_CREAT, 0644)) != -1)
        {
            fprintf(stderr, "Dupping stdout to %s\n", redirect[1]);
            dup2(fd, STDOUT_FILENO);
            close(fd);
        }
    }

    if (command[0][0] == '/')
    {
        execv(command[0], command);
        fprintf(stderr, "ERROR: command %s does not exist at path specified\n", command[0]);
        return(1);
    }
    else
    {
        fprintf(stderr, "ERROR: not handling relative names like %s\n", command[0]);
        return(1);
    }
    return 0;
}

This code works too, not redirecting to file:

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

int main(void)
{
    int fd;
    char *redirect[] = { "<", "file.in" };
    char *command[] = { "/bin/ls", "-l", 0 };

    if (!strcmp(redirect[0], ">"))
    {
        if ((fd = open(redirect[1], O_WRONLY | O_CREAT, 0644)) != -1)
        {
            fprintf(stderr, "Dupping stdout to %s\n", redirect[1]);
            dup2(fd, STDOUT_FILENO);
            close(fd);
        }
    }

    if (command[0][0] == '/')
    {
        execv(command[0], command);
        fprintf(stderr, "ERROR: command %s does not exist at path specified\n", command[0]);
        return(1);
    }
    else
    {
        fprintf(stderr, "ERROR: not handling relative names like %s\n", command[0]);
        return(1);
    }
    return 0;
}

Note that it sets up the command array and uses execv(command[0], command); — this is the recommended way of doing business. Your code appears to have a variable commands with presumably the arguments to the program; you also appear to have a variable path with presumably the path name of the program. Since we can't see what's in those, it is hard to know what they contain and where there might be problems. Note the explicit null pointer (0) at the end of the command array. That is crucial. Note too that the error messages identify what was failing. There are few things more frustrating than a program that says "it went wrong" without identifying what 'it' is.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • The permissions on the file that is created. When you use `open()` with `O_CREAT`, it is a function that takes 3 arguments; otherwise, it takes just 2 arguments. The third argument is the permissions to set on the file, which will be modified by the `umask` setting. The mode 0644 is read/write for owner, read-only for group and others. There are ways to write that symbolically (`S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH`) but frankly that takes me longer to comprehend than 0644 does — by a large margin. – Jonathan Leffler Jan 30 '14 at 14:39
  • If you don't mind, could I send you a copy of my entire solution, I'd post it here, but I don't think my instructor would appreciate that. I still can't figure out why it's behaving as it is. – d0m1n1c Jan 30 '14 at 14:45