What is the difference in using Ctrl+D and Ctrl+C to terminate cat command?

cat
14,730

Solution 1

When the cat command is running, the terminal is in canonical input mode. This means, in short, that the terminal's line discipline is handling line editing, and is responding to all of the special characters configured for the terminal (viewable and settable with the stty command).

The cat command is simply read()ing from its standard input until a read() call returns zero bytes read, the POSIX convention for hitting end of file.

Terminals do not really have an "end". But there is a circumstance where read() of a terminal device returns zero bytes. When the line discipline receives the "EOF" special character, whatever that happens to be configured as at the time, it causes read() to return with whatever is in the editing buffer at that point. If the editing buffer was empty, that returns zero bytes read from read(), causing cat to exit.

cat also exits in response to signals whose default actions are to terminate the process. The line discipline also generates signals in response to special characters. The "INTR" and "QUIT" special characters cause the INT and QUIT signals to be sent to the foreground process (group), which will be/contain the cat process. The default action of these signals is to terminate the cat process.

Which leads to the observable differences:

  • Ctrl+D only has this action when it is the EOT special character. This is usually the case, but it is not necessarily the case. Similarly, Ctrl+C only has its action when it is the INTR special character.
  • Ctrl+D will not cause cat to terminate when the line is not in fact empty at the time. An interrupt generated by Ctrl+C will, though.
  • A naïve implementation of cat in the C language will block buffer standard output if it finds it directed at a file, as in the question. In theory, this could lead to buffered and not yet output lines being lost if cat is terminated by SIGINT.

    In practice, the BSD and GNU C libraries implement a buffering mode that is not described in the C or C++ language standards. Standard output when redirected to file or pipe is smart buffered. It is block buffered; except that whenever the C library finds itself about to read() the beginning of a new line from any file descriptor that is open to a terminal device, it flushes standard output. (The BSD and GNU C libraries do not quite implement the same semantics and do more than this, strictly speaking, but this behaviour is a common subset.) Thus an interrupt signal will not cause lost buffered output when cat is built on top of such a C library.

  • Of course, if cat is part of a command pipeline, some other process could be buffering the data, downstream of cat before those data reach an output file. So again when the line discipline sends SIGINT, which (by default) terminates all of the processes in the pipeline, input data buffered and not yet written will be lost; whereas terminating cat normally with the "EOF" special character will cause the pipeline to terminate normally, with all of the data passing to the downstream process before it receives an EOF indication from its read() of its standard input.

Note that this bears very little relationship to what happens when your interactive shell is reading a line of input from you. When your shell is waiting for input, the terminal is in non-canonical input mode, in which mode the line discipline does not do any special handling of special characters. How your shell treats Ctrl+D and Ctrl+C is entirely up to the input editing library that your shell uses (libedit, readline, or ZLE) and how that editing library has been configured (with key bindings and suchlike).

Further reading

Solution 2

CTRL+C is an interrupt signal. It will stop the command.

CTRL+D is end of file or exit(). When you entered CTRL+D , it exited from the command because of end of file. If you type CTRL+C in your shell nothing will happen. However, if your enter CTRl+D, it will exit from your current Shell in most systems.

Share:
14,730

Related videos on Youtube

Sonevol
Author by

Sonevol

Sexually I am transsexual lesbian. Please consider me to be female and address me by "she" and "her" and be compassionate to my feelings. Pets are my love and my pet Bhutu (female balck and white tuxedo cat) means everything to me. Also I love my mom, my grand-mom and the girl named Puja. I also love the two children which Puja has. We six are almost family. I like UNIX and UNIX based operating systems. I love to play around with Linux and learn newer things. Professionally I am front end web developer working independently. Also I am a weed addict.

Updated on September 18, 2022

Comments

  • Sonevol
    Sonevol almost 2 years

    I have the following two test files:

    test1 test2
    

    Both of them are blank. Now I issue the following commands:

    $ cat > test1  
    

    Enter

    This is a test file
    

    Enter

    Ctrl + D

    $ cat > test2
    

    Enter

    This is another test file
    

    Enter

    ^C
    

    Ctrl + C

    $
    

    Now I check the contents of the two files

    $ cat test1
    This is a test file
    $ cat test2
    This is another test file
    $
    

    So is there any real difference in the outcome if we use the above two methods to achieve the same outcome?

  • Sonevol
    Sonevol almost 7 years
    Apart from what are they according to definition is there any change in outcome or the outcome will always be the same, whichever method you use?
  • user996142
    user996142 almost 7 years
    @Sonevol different. CTRL+D works like EOF and CTRL+C is intr (check stty -a for these settings of line discipline). Try cat > foo.txt. Type something, click CTRL+D and check foo.txt. Check it with CTRL+C then.