I have written a set of programs with the intent of using a radio transmitter-receiver (NRF24L01) to connect two devices as if they were connected via a serial interface.

Currently, i am able to send bash commands in one direction, lets say from device A to B. My A device is currently an AVR microcontroller.

My B device is a Rapberry Pi. I use the following command to pipe the received text to bash. This allows commands to be sent but not for their output to be sent back to the A device.

./program | bash

I am not sure how to pipe the output from bash back into my program in a way that will not block and prevent the program from reacting to received data. If it is possible to setup a pipe in both directions, I still do not think I can use functions like fgets as they are blocking.

Both devices share the same library for transmit and receive functionality, these transmit and receive functions can be called with an option to make them non-blocking.


The easiest approach is probably to have your program use pipe2 three times to create three pipes (for each of stdin, stdout, and stderr). Probably you want them in non-blocking mode. Then fork, and have the child use dup2 to put the pipes into file descriptors 0, 1, and 2. The child then uses one of the exec family to run bash.

The parent can then use select to determine when there is data to be read or space to write.

There are probably libraries or existing implementations you could leverage.

Note #1: pipe2 returns two file descriptors, one for the read side and one for the write side of the pipe. E.g., for bash's stdin, bash needs the read side (to read input) and your program needs the write side (to write bash's input). bash's stdout would be the opposite: bash needs the write side, your program needs the read side.

Note #2: This doesn't give you a full terminal experience; for that you'd need to deal with ptys, which adds a bunch of complexity (and honestly I'd have to look it up). If you want that, I definitely suggest looking for a similar program to start from.

  • would you or someone else be willing to elaborate on what functionality will be missing without using ptys? I envision the utility of this code to be accessing remote sensors and non-security-critical equipment. – fisherdog1 Jun 7 at 17:56
  • you know, there are other bi-directional pipes besides ttys. look up socketpair() -- much better than pipe() even if you leave one direction unused (because you can turn record mode on with SEQ_PACKET, peek instead of read with recv(MSG_PEEK), use it in non-blocking mode on a per-call basis, authenticate the pair, etc, etc – Uncle Billy Jun 7 at 18:33
  • @fisherdog1 A lot of stuff won't work. E.g., control-C probably won't. Anything trying to do terminal "drawing" or positioning probably won't. – derobert Jun 7 at 18:39
  • @UncleBilly I doubt SOCK_SEQPACKET would work; that's not the behavior expected of STDIN/OUT/ERR. SOCK_STREAM probably would, though. – derobert Jun 7 at 18:42
  • @fisherdog1 (Basically, to get it all working, you'd be implementing a minimal telnet client & server, just using your radio interface instead of a TCP connection — which may well be a good place to look for code to build on.) – derobert Jun 7 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.