On an older RHEL system I've got, /bin/cat
does not loop for cat x >> x
. cat
gives the error message "cat: x: input file is output file". I can fool /bin/cat
by doing this: cat < x >> x
. When I try your code above, I get the "looping" you describe. I also wrote a system call based "cat":
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int
main(int ac, char **av)
{
char buf[4906];
int fd, cc;
fd = open(av[1], O_RDONLY);
while ((cc = read(fd, buf, sizeof(buf))) > 0)
if (cc > 0) write(1, buf, cc);
close(fd);
return 0;
}
This loops, too. The only buffering here (unlike for stdio-based "mycat") is what goes on in the kernel.
I think what's happening is that file descriptor 3 (the result of open(av[1])
) has an offset into the file of 0. Filed descriptor 1 (stdout) has an offset of 3, because the ">>" causes the invoking shell to do an lseek()
on the file descriptor before handing it off to the cat
child process.
Doing a read()
of any sort, whether into a stdio buffer, or a plain char buf[]
advances the position of file descriptor 3. Doing a write()
advances the position of file descriptor 1. Those two offsets are different numbers. Because of the ">>", file descriptor 1 always has an offset greater than or equal to the offset of file descriptor 3. So any "cat-like" program will loop, unless it does some internal buffering. It's possible, maybe even likely, that a stdio implementation of a FILE *
(which is the type of the symbols stdout
and f
in your code) that includes its own buffer. fread()
may actually do a system call read()
to fill the internal buffer fo f
. This may or may not change anything in the insides of stdout
. Calling fwrite()
on stdout
may or may not change anything inside of f
. So a stdio-based "cat" might not loop. Or it might. Hard to say without reading through a lot of ugly, ugly libc code.
I did an strace
on the RHEL cat
- it just does a succession of read()
and write()
system calls. But a cat
doesn't have to work this way. It would be possible to mmap()
the input file, then do write(1, mapped_address, input_file_size)
. The kernel would do all the work. Or you could do a sendfile()
system call between the input and output file descriptors on Linux systems. Old SunOS 4.x systems were rumored to do the memory mapping trick, but I don't know if any one has ever done a sendfile-based cat. In either case the "looping" wouldn't happen, as both write()
and sendfile()
require a length-to-transfer parameter.
I had the same issue, my dmesg was full with this messages, and could not unmount nor suspend the computer:
[ 4095.313680] usb usb4-port5: Cannot enable. Maybe the USB cable is bad?
[ 4099.301425] usb usb4-port5: Cannot enable. Maybe the USB cable is bad?
[ 4103.293161] usb usb4-port5: Cannot enable. Maybe the USB cable is bad?
I discovered it happens when keep a long time without unplugging the USB devices. Maybe the controller on some device goes erratic after staying so much time on, and going trough so many suspends and it is sending bad signals.
I discovered this fixes the problem:
- unplug all your USB devices;
or
- power off your computer and power off also the button which comes with the PSU (Power supply unit) because otherwise the PSU will still give juice to the motherboard and will still power the USB controllers on the device attached to it.
And of course sometimes can also be a bad cable. See here: https://askubuntu.com/a/348799/82315
Best Answer
I think for serial devices you have to set the baud rate before they do anything. I'm not sure how to do that from the command line in order to get
cat
to work, but you could use a terminal emulator which takes care of it.Try
minicom
orscreen
(i.e.screen /dev/ttyUSB0 115200
- replace 115200 with the baud rate of your IR receiver.)