2

I have a python script that generates a file (cap.pcap). when I execute cat on it, it gets stuck forever (doesn't display anything). I tried to run:

  1. The commands file, hd and vi. They work properly.
  2. lsof and fuser, they show nothing.
  3. cp to another file and cat on the latter. It gets stuck.
  4. dd to another file, same result.
  5. < base64 cap.pcap > b64; < base64 -d b64 > cap2.pcap; cat cap2.pcap; It gets stuck again.
  6. Sent the base64 content to another machine and tested it; it worked properly.

Also, when I execute cat on any other file: it works.

Versions:

  • Ubuntu 18.04.1
  • cat (GNU coreutils) 8.28

Just in case it might help, the part of the following python script is responsible of this:

import pcapy
data = []

cap = pcapy.open_live("enp0s3" , 65536 , 1 , 0)
dumper = cap.dump_open('cap.pcap')
for i in range(20):
    hdr, pkt = cap.next()
    dumper.dump(hdr, pkt)
    if i%10 == 9:
        f = open('cap.pcap', 'rb+')
        data += f.read();
        f.truncate(0)
        f.close()
dumper.close()
zeralight
  • 121
  • That actually works. But the main question is why it makes the cat blocked and why when it gets executed on another machine, cat doesn't block. – zeralight Nov 04 '18 at 02:15
  • 1
    I don't understand your redirections in point 5. It's unclear what you're actually doing there. – Kusalananda Nov 04 '18 at 08:15

2 Answers2

3

Short answer

  1. You can almost always assume it's not cat's fault; it is too widespread, well-tested and simple to have such big, obvious bugs.
  2. Don't just cat a binary file to your terminal; terminals are designed to show text, not arbitrary binary data.

Long answer

It is not the cat process itself that gets stuck, but the terminal emulator, i.e. the program displaying the window. cat itself couldn't care less about what is actually in the file, all it does is copy whatever is in it to its stdout¹. You can (theoretically) cat /dev/sda and it would happily dump your entire HDD contents onto your terminal.

Terminal emulators are however not designed to show any arbitrary binary data. They are made to show text, and it is possible to control how the text is displayed by embedding special sequences of non-printable characters in them, called control codes or escape codes, as most of them start with the "escape character" (\x1B, often displayed as ^[).

Now if you dump binary data onto your terminal, it may see an escape character (or any other character that is special to it), and try to interpret an escape code from it. This means it will not display the following characters, at least until it can decide whether they actually form a valid sequence or not. Another possibility is that there's a valid sequence embedded somewhere that triggers special behaviour, like blanking the terminal (and making it look like nothing was printed at all), or changing the foreground color (and making all subsequent output invisible).

I'll assume that on the two different computers you were testing on, you used different terminal emulators, which would explain the different behaviours you were seeing: not all TEs recognize all escape codes, as some implement private, non-standard sequences for some unique behaviours (like kitty's raster image displaying protocol).

¹) There are some flags to cat, such as -t which was suggested in the comments, that make it manipulate the file contents before outputting them. See man cat for more info.

What you can do

Sometimes you may want or need to look at the actual bytes within a file. In these situations you should use a specialized software called a hex editor, which displays the hexadecimal representation of each byte in the file, thus making it safe to print on a terminal.

For simple viewing purposes, you can also use the xxd program, which may be shipped with vim or standalone (depending on your distribution).

You can extract the various texts that might be present in any binary file by using strings, which is included in binutils in most distros. (Thanks to @Rui F Ribeiro for pointing it out)

1

A pcap file is generated by the libpcap library. It is not a text file. It is a file in a special raw format that is a dump of network traffic.

The command tcpdump understands such format.

To see the headers of tcp/ip traffic do:

tcpdump -r cap.pcap -n

To see captured traffic too:

tcpdump -r cap.pcap -n -s 1500 -X
Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232