Skip to content

Conversation

@VivianBelle17
Copy link

@VivianBelle17 VivianBelle17 commented Oct 4, 2025

FogOS tee

Build

  1. make clean

  2. make

  3. make qemu

After running these commands, run ls to make sure the tests directory is listed so you can run the tests below!

Purpose

tee reads from standard input and writes it to both standard output and up to 10 files at a time.

The command tee [file] will read from standard input and write the contents of what was just added to both the standard output and the specified file. If the file does not exist, it will be created. If it does exist, it will be overwritten by default.

The -a flag can be used as well. When tee -a [file] is used, it will append the input to the end of the given file(s), without overwriting it.

  • Note: If using standard input (e.g. keyboard) to write to these files, every line entered will be written to standard output and to the file(s) until ctrl+d is pressed.

If you would like to see if it worked, use the cat command!

    cat file.txt

Examples

Check the results using cat [file]


  1. Creates a file test.txt and reads from standard input. Once you press enter and ctrl+d, what you wrote is written to the terminal and to the file!

     tee test.txt 
    
    • Your input will be printed to the terminal and written to the newly created file test.txt
    • See result: cat test.txt

  1. Appends to test.txt using the -a flag.

     tee -a test.txt
    
    • Your input will be printed to the terminal and appended to the existing test.txt
    • See result: cat test.txt

  1. Using echo to add Hello to file1.txt

     echo Hello | tee file1.txt 
    
    • Only Hello will be printed to the terminal and written to the newly created file file1.txt
    • See result: cat file1.txt

  1. Copying the contents of test.txt into copied.txt

     cat test.txt | tee copied.txt
    
    • Only the contents of test.txt will be printed to the terminal and written into the newly created file test.txt
    • See result: cat copied.txt

  1. Using the test files, if you append sqd_btm.txt to sqd_top.txt hit enter and cat tests/sqd_top.txt you will get an ASCII drawing of squidward!

     cat tests/sqd_btm.txt | tee -a tests/sqd_top.txt
    
    • Only the contents of tests/sqd_btm.txt will be printed to the terminal and appended to the existing file tests/sqd_top.txt
    • See result: cat tests/sqd_top.txt

  1. This examples demonstrates appending to multiple files. It appends the first fish ascii art into the other 2 fish files.

     cat tests/fish.txt | tee -a tests/fish1.txt tests/fish2.txt
    
    • Only the contents of tests/fish.txt will be printed to the terminal and appended to the existing files
    • See results: cat tests/fish1.txt & cat tests/fish2.txt

  1. This shows a more useful way to use this command. If you would like to pull out any error messages from one file and put it in another file, you can! In this case, grep searches for the word The in brwn_fox.txt and prints out and writes the lines that contain The to find.txt.

     grep The tests/brwn_fx.txt | tee find.txt
    
    • All 6 lines in the file will be printed to the terminal and written to the newly created file find.txt
    • See result: cat find.txt

  1. Here is another one! For this example, all the lines that include can't in gingerb.txt is appended to the find.txt that was created above.

     grep can't tests/gingerb.txt | tee -a find.txt
    
    • The lines 2, 3, 4, and 6 will be printed to the terminal and appended to the existing file find.txt
    • See result: cat find.txt

@MichaelBooyers
Copy link

I will code review this

@DemetriusChatterjee
Copy link

DemetriusChatterjee commented Oct 6, 2025

After make qemu, the test folder shows up in the listing. "tee [file]" works in creating a file (not only limited to text files, but that was not part of the description, so it's alright for the program to do that.) When using "tee -a [file]" and the "tee [file]", after writing a line to qemu, it is printed back, and the user might think they have written to the file twice.

NOTE: When running "cat" on the recently appended file, it shows only the number of lines that the user entered. I suggest removing the confusion by removing the output line that prints the line the user just typed in. Additionally, you can also output the contents of the file first when opening it with append mode to help the user understand what contents are already in the file.

Additionally, "tee -a [file]" when used with a file that did not exist does not return an error but instead creates the file and writes to it. It works for writing error messages as well. The code formatting is generally consistent and follows the style of the other user-space utilities in the project. There are no major formatting issues to address. Good Job!

High Level Checks:
[x] PR fully resolves the task/issue. (Although it technically resolves the task, consider the note I left to make it less confusing for the user)
[X] Does the PR have tests?
[X] Does the PR follow project code formatting standards?
[X] Does the OS still compile and run?
[X] Is documentation included?

Code Checks:
[x] Does the code achieve its intended purpose?
[x] Were all edge cases considered?
[x] Is the code organized and maintainable?
[x] Does the code maintain the same level of performance?

@ersutera
Copy link

ersutera commented Oct 6, 2025

✅ PR fully resolves the task/issue
✅ Does the PR have tests?
✅ Does the PR follow project code formatting standards?
✅ Does the OS still compile and run?
✅ Is documentation included?

✅ Does the code achieve its intended purpose?
✅ Were all edge cases considered?
✅ Is the code organized and maintainable?
✅ Does the code maintain the same level of performance? (no performance regressions)

Your tests and walkthrough are clear, concise, and easy to follow. Running the provided commands worked as expected.

Your code is clean, well-documented, and easy to understand. Variable names and comments are clear, and formatting is consistent throughout.

The code correctly initializes fds for up to 10 files, so the 7-file cap isn’t caused by your implementation. After checking, it seems to stem from the MAXARGS definition (set to 10) in sh.c. Adjusting that constant would allow handling all 10 files. So this isn’t an error in your PR, just a shell-level limit worth noting.

Summary:
The README.md is very clear and detailed, which I appreciated.
Code is well-written and organized.
Tests are effective and easy to follow.
Behavior aligns with documentation and expectations.
The only limitation observed is external (MAXARGS).
Excellent work overall — clear, consistent, and functional.

@MichaelBooyers
Copy link

MichaelBooyers commented Oct 10, 2025

Verification

The goals you described in the issue is exactly what this pull request fulfills! The tee command and -a flag work as they are supposed to as according to your documentation. No functionality missing!

Testing

The test folder and walkthrough you provided are very clear and concise. It is easy to follow along and understand what is expected when running a command and it's usage. I did find the Squidward drawing by doing tee -a amazing! But proves that your test cases work as you provided some and other various examples.

I did however run into an interesting detail that will be mentioned in the code walkthrough as well...
Say we have the command: 'cat tests/fish.txt | tee -a test1.txt {...}'

When running cat and piping that output as the input for tee, you can only write up to 7 files. It's not the 10 from earlier documentation, however if we remove 'cat' and piping and solely do 'tee test1.txt {...}' we can then write up to 8 files.

Small issue but it works as expected.

Code Walkthrough

Code wise, documentation, comments, variable names are all good. It's easy to read your code and to understand what is happening. I would make some change to the code error logic but it's me being a nitpick since I worry about errors a lot.

You wrote:

fds[i - file_start] = open(argv[i], flags);
fd_count++;

But then after you check if 'i - file_start < 0' as a check, I personally would put the condition first to see if we should attempt our open() or to print an error otherwise. It's not anything major and as I said me being too picky.

As for the error when writing up to 7 files or 8 files, on my initial look, I thought perhaps you handled arguments in a different way but you did initialize fds to 10, so that's correct. You also don't handle or affect other areas of the code, but I did look in sh.c and there is a MAXARGS definition set to 10. So code wise if you wanted to get your '10 files at once' to work, this may need to be changed. But, I think it's good to note the only 'error' presented by your code isn't your fault!

Formatting was consistent. Everything looks really good. Amazing work!

High Level Checks:

  • PR fully resolves the task/issue
  • Does the PR have tests?
  • Does the PR follow project code formatting standards?
  • Does the OS still compile and run?
  • Is documentation included?

Code Checks:

  • Does the code achieve its intended purpose?
  • Were all edge cases considered?
  • Is the code organized and maintainable?
  • Does the code maintain the same level of performance? (no performance regressions)

@malensek
Copy link
Contributor

Looks great! Tee is a fun utility. Cool project.

Here's what I found:

  • Byers is right about not counting fds that fail to open.
  • I think bytesToRead is misleadingly named -- it's the number of bytes that were read
  • I don't think tee would normally add an extra newline to the end of the file... actually wait, that's not what this is doing! It's adding a newline to the end of the buffer, which is 512 so probably big enough to fit most test files except fish2.txt. Luckily at exactly 512 bytes in that file there was already a newline. Set data to something small and observe what happens: it should have no impact on the output (other than making things slower) but does in fact wrap all the files at the buffer size. This definitely needs to be fixed!
  • The comments are redundant, e.g., closing files -> closes the files. Writing to a file -> write() to a file. This looks like straight up LLM style commenting but no LLM was cited. Regardless the comment verbosity needs to be turned down a notch.

4.5/5
+0.5 for the fixes above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants