Make two programs communicate with each other

C and PERL communicating via keyboard status lights

My friend and I got inspired by this one last night.

We use Perl for the sender program and C for the receiver.

The medium of exchange was the keybord status lights!

Three virtual signal lines were used: Caps Lock, Num Lock and Scroll lock, being used as Clock, Serial Data, and Start Of Byte signals.

Data and signals

The sender program pulses those keyboard lights and the receiver polls them and checks the state. Data is sent serially as binary, in 8 bit bytes.

You can see the transmitter and receiver programs in operation, in the attached video, as well as the flashing of the lights during the transmission. Video of operation

Source for both programs is attached. Given the question requirements, we didn't try to minimize the size like we would in a normal golfing attempt.

C Code (receiver)

#include <X11/Xlib.h>
#include <stdio.h>
#include <unistd.h>

int main(void)
{
    Display* dpy = XOpenDisplay(":0");
    XKeyboardState x;
    char keys_return[32];
    int b = 0;
    while (1) {
        unsigned char output = 0;
        printf(" \b");
        fflush(stdout);
        while (XQueryKeymap(dpy, keys_return)) //wait for start signal
            if (keys_return[9] == 64) {
                break;
            }
        for (b = 0; b < 8; b++) {
            do {
                XGetKeyboardControl(dpy, &x);
            } while (!(x.led_mask & 1)); //wait for clock to be high
            if (x.led_mask & 2)
                output |= 128;
            if (b != 7)
                output >>= 1;
            do {
                XGetKeyboardControl(dpy, &x);
            } while ((x.led_mask & 1)); //wait for clock to be low
        }
        printf("%c", output);
    }
    XCloseDisplay(dpy);
    return 0;
}

PERL code (transmitter)

use X11::Xlib ':all';
use strict;
use warnings;
use feature 'say';
use Time::HiRes qw(sleep);

use constant {
    DATA  => 77,
    START => 78,
    CLOCK => 66
};

my $display = X11::Xlib->new;

sub transmit_str {
    my ($str) = @_;
    foreach my $char ( split( //, $str ) ) {
        my $ordchar = ord($char);
        for my $i ( 0 .. 7 ) {
            for my $j ( 0 .. 1 ) {
                if ( $i == 0 ) {
                    $display->fake_key( START, !($j) );
                }
                if ( $ordchar & 1 ) {
                    $display->fake_key( DATA, 1 );
                    $display->fake_key( DATA, 0 );
                }
                $display->flush;
                sleep(0.025) if(!$j);
                $display->fake_key( CLOCK, 1 );
                $display->fake_key( CLOCK, 0 );
                $display->flush;
                sleep(0.05);
            }
            $ordchar >>= 1;
        }
    }
}
while ( my $stdin = <STDIN> ) {
    transmit_str($stdin);
}

Original Lisp Eliza communicating with yes

Original Eliza lisp code "communicating" with with unix yes utility.

First create a FIFO special file:

mkfifo in

Then we make the two programs communicate together (which means that the patient will answer YES to all questions).

clisp coselleliza1969and1972.lisp < in | tee out.txt | yes 'yes.'  > in

Output is inifnite and starts with:

TELL ME YOUR PROBLEMS. PLEASE TERMINATE INPUT WITH A PERIOD OR A QUESTION MARK.
IS THERE SOMETHING BOTHERING YOU?
WHY ARE YOU SO SURE?
I SEE.
I UNDERSTAND.
CAN YOU BE MORE INFORMATIVE?
WHY ARE YOU SO SURE?
I SEE.
I UNDERSTAND.
PERHAPS YOU'D RATHER TALK ABOUT SOMETHING ELSE.

More variety if it communicates with another instance of itself:

clisp coselleliza1969and1972.lisp < in | clisp coselleliza1969and1972.lisp | tee out.txt > in

Output starts with:

TELL ME YOUR PROBLEMS. PLEASE TERMINATE INPUT WITH A PERIOD OR A QUESTION MARK.
WHY ARE YOU CONCERNED OVER MY PROBLEMS?
I AM NOT SURE I UNDERSTAND YOU FULLY.
SUPPOSE * WHY WERE NOT I CONCERNED OVER YOUR PROBLEMS.
IS IT BECAUSE YOU ARE NOT SURE YOU UNDERSTAND I FULLY THAT YOU CAME TO ME?
YOU SAY YOU CONCERNED OVER MY PROBLEMS?
POSSIBLY THAT IS FOR THE BETTER.
SUPPOSE YOU SAY I CONCERNED OVER YOUR PROBLEMS.
POSSIBLY * POSSIBLY THAT REALLY IS NOT FOR THE BETTER.
OH? I SAY YOU CONCERNED OVER MY PROBLEMS?
WHAT IF REALLY WERE FOR THE BETTER?
PLEASE GO ON.
CAN YOU ELABORATE ON THAT?
WHAT DOES THAT SUGGEST TO YOU?
TELL ME MORE ABOUT YOUR PROBLEMS.
WHAT MAKES YOU THINK I ELABORATE ON THAT?
PERHAPS THAT CONCERNS YOUR PROBLEMS.
WHAT ABOUT YOUR OWN PROBLEMS?
WHO ARE YOU REALLY TALKING ABOUT?
YOU DON'T SEEM QUITE CERTAIN.
EARLIER YOU SAID YOU WERE NOT SURE YOU UNDERSTAND I FULLY.
TELL ME MORE ABOUT * WHO.
SUPPOSE YOU DON'T SEEM QUITE CERTAIN.
OH? I SAID I WAS NOT SURE I UNDERSTAND YOU FULLY?
ARE YOU STILL NOT SURE YOU UNDERSTAND I FULLY?
WHAT MAKES YOU THINK I DON'T SEEM QUITE CERTAIN?
WOULD YOU LIKE TO DISCUSS YOUR PROBLEMS?
DO YOU SAY YOU SAID YOU WAS NOT SURE YOU UNDERSTAND I FULLY FOR SOME SPECIAL REASON?
DID YOU THINK * MIGHT NOT BE I STILL NOT SURE I UNDERSTAND YOU FULLY?
WHO ARE YOU REALLY TALKING ABOUT?
SUPPOSE YOU LIKE TO DISCUSS MY PROBLEMS.
OH? I SAY I SAID I WAS NOT SURE I UNDERSTAND YOU FULLY FOR SOME SPECIAL REASON?
WHAT MAKES YOU THINK I THINK * MIGHT NOT BE YOU STILL NOT SURE YOU UNDERSTAND I FULLY?
* WHO PERHAPS ARE I REALLY TALKING ABOUT.
WHO ARE YOU REALLY TALKING ABOUT?
WHAT ELSE WOULD YOU LIKE TO DISCUSS?
TELL ME MORE ABOUT YOURSELF?
SUPPOSE YOU THINK YOU THINK * MIGHT NOT BE I STILL NOT SURE I UNDERSTAND YOU FULLY.
WHY THE UNCERTAIN TONE?
SUPPOSE * WHO WERE NOT I REALLY TALKING ABOUT.
OH? I LIKE TO DISCUSS?
WHY DO YOU SAY THAT JUST NOW?
WHAT MAKES YOU THINK I THINK I THINK * MIGHT NOT BE YOU STILL NOT SURE YOU UNDERSTAND I FULLY?
I AM NOT SURE I UNDERSTAND YOU FULLY.
OH? YOU REALLY TALKING ABOUT?
PLEASE GO ON.
WHAT ELSE DO YOU LIKE?
WHO ARE YOU REALLY TALKING ABOUT?
SUPPOSE YOU THINK YOU THINK YOU THINK * MIGHT NOT BE I STILL NOT SURE I UNDERSTAND YOU FULLY.
HOW LONG HAVE YOU BEEN NOT SURE YOU UNDERSTAND I FULLY?
DID YOU TELL ME YOU WERE NOT SURE YOU UNDERSTAND I FULLY?
OH? I REALLY TALKING ABOUT?
MAYBE NOW WE CAN DISCUSS WHY YOU ARE NOT SURE YOU UNDERSTAND I FULLY.
WHAT MAKES YOU THINK I LIKE?
POSSIBLY * WHO REALLY ARE NOT I REALLY TALKING ABOUT.
WHO ARE YOU REALLY TALKING ABOUT?
SUPPOSE YOU BEEN NOT SURE I UNDERSTAND YOU FULLY.
OH? I TELL YOU I WAS NOT SURE I UNDERSTAND YOU FULLY?
WOULD YOU LIKE TO DISCUSS YOUR PROBLEMS?
THAT'S QUITE INTERESTING.

Bash and GNU Awk communicating on TCP

Bash transmitter:

cat>/dev/tcp/localhost/8080

GNU Awk receiver:

BEGIN{getline<"/inet/tcp/8080/0/0";print}

Sample run:

Bash in terminal 1:

bash-4.2$ cat>/dev/tcp/localhost/8080
Bash says hello to Awk
^D

GNU Awk in terminal 2:

bash-4.2$ gawk 'BEGIN{getline<"/inet/tcp/8080/0/0";print}'
Bash says hello to Awk

Both bash and gawk provides special filenames (/dev/tcp/host/port in bash since 2.04, /net-type/protocol/local-port/remote-host/remote-port in gawk since 3.1.0) for simple networking. These are extensions not specified in the POSIX shell and Awk language standards.