0

I'm in an operating systems course and doing assignments with C on Linux. In one of the assignments I was supposed to redirect and output to a file, but for some reason, I keep getting the output in the terminal instead. I tried writing a simple program to do just that and it still didn't work:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <dirent.h>

void main(int argc, char* argv[]) {
    int file1 = open("./text_try", O_CREAT | O_EXCL, 0666) //open file
    printf("write to screen\n"); //print to screen
    int oldOut = dup(1); //save screen FD
    dup2(file1,1); //change output stream from screen to file
    printf("write to file"); //print to file
    dup2(oldOut,1); //change output stream from file back screen 
    printf("write to screen");  //print to screen
}

other things I tried :

  1. changing the permissions on the file open (adding O_RDWR)
  2. running on 2 separate PCs - i run mainly on remote desktop to the uni pc for linux but also got VMware on the laptop.
  3. tried using close + dup combo instead on dup2
  4. tried using conditions with perror to see if any step will tip me off as to why it doesn't work.
  5. tried using STDOUT_FILENO instead of 1 for output

would really appreciate any help on this!

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
  • 1
    Start with adding error checking. `open()`, `dup2()`, etc. can fail and you need to handle it when they do. – Shawn Jan 01 '22 at 16:41
  • Also read up on `open()` and what should be included in the second argument if you want to be able to write to that file. – Shawn Jan 01 '22 at 16:43
  • For starters, remove the `O_EXCL` flag. That open call will fail if `text_try` already exists from a previous run. – selbie Jan 01 '22 at 17:08

1 Answers1

1

stdio normally buffers output to stdout -- it's line-buffered when it's connected to a terminal, fully-buffered when connected to a file. Since you're not writing any newlines, it will not flush the buffer automatically in either mode. The buffer is flushed automatically when the program exits, at which time it gets written to the last stream that FD 1 is connected to.

Either turn off buffering with setvbuf(), or flush the output explicitly between printf() calls.

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <dirent.h>

void main(int argc, char* argv[]) {
    int file1 = open("./text_try", O_CREAT | O_EXCL, 0666) //open file
    printf("write to screen\n"); //print to screen
    int oldOut = dup(1); //save screen FD
    dup2(file1,1); //change output stream from screen to file
    printf("write to file"); //print to file
    fflush(stdout);
    dup2(oldOut,1); //change output stream from file back screen 
    printf("write to screen");  //print to screen
    fflush(stdout);
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • OMG IT WORKED ! can you please explain a little more plainly why it works this way ? or maybe refer me to an article about it? THANK YOU SO MUCH ! – Lidor Cohen Jan 01 '22 at 16:58
  • Does this work the same for input but with fflush(stdin)? – Lidor Cohen Jan 01 '22 at 17:07
  • `fflush()` causes undefined behavior on input streams. There are some implementations that extend it to input streams, but it's not standard. See https://stackoverflow.com/questions/2979209/using-fflushstdin – Barmar Jan 01 '22 at 17:08
  • just tried using fflush(stdin) and it worked also ! did it right after scanf since i assumed that scanf is "the opposite" of printf – Lidor Cohen Jan 01 '22 at 17:26
  • As I said, it depends on the implementation. – Barmar Jan 01 '22 at 17:27
  • So don't use it in code that should be portable. – Barmar Jan 01 '22 at 17:28
  • unfortunately it's supposed to be portable... know any other implementation that would work instead ? – Lidor Cohen Jan 01 '22 at 18:17
  • [how to clear input buffer in c](https://stackoverflow.com/questions/7898215/how-to-clear-input-buffer-in-c) [how to clear stdin before getting new input](https://stackoverflow.com/questions/36715002/how-to-clear-stdin-before-getting-new-input) – Barmar Jan 01 '22 at 18:22