By vomv1988I want to develop a script of the following form:
Code:
#!/bin/bash
# Function ‘listen’ opens a data stream
# which stores all incoming bytes in
# a buffer, preparing them to be
# grabbed by a following function
# which appears at random
# intervals during the execution of
# the script
listen &
INPID=${!}
# To test if the script is really capable
# of grabbing bytes randomly, the
# following code is looped over:
PROMPT=n
while test ${PROMPT} != ‘q’ ; do
printf ‘y: print next bytenn: don'”‘”‘t print next bytenq: quitn’
read -n 1 PROMPT
printf ‘n’
if test ${PROMPT} = ‘y’ ; then
# The function ‘grab1byte’ extracts
# ONE byte from the buffer being fed
# bytes by ‘listen’, and outputs it
# to stdout
INBYTE=`grab1byte`
echo The input byte is:
printf “${INBYTE}” | xxd -cols 1 | sed ‘s/^.*: //’
fi
done
kill ${INPID}
The way I’ve tried to implement this, is by using FIFOs. In one directory, I have 2 FIFOs, which I created with mkfifo; these are named ‘INPUT‘ and ‘FIFO‘. In fluxbox, I open 2 instances of xterm; in one I run the following script:
Code:
#!/bin/bash
MY_INPUT=INPUT
MY_FIFO=FIFO
# This is ‘listen’:
(
IFS=
tail -f ${MY_INPUT} | while read -N 1 CHAR ; do
printf “${CHAR}” > ${MY_FIFO}
done
) &
READPID=${!}
PROMPT=n
while test ${PROMPT} != ‘q’ ; do
printf ‘y: print next bytenn: don'”‘”‘t print next bytenq: quitn’
read -n 1 PROMPT
printf ‘n’
if test ${PROMPT} = ‘y’ ; then
# This is ‘grab1byte’:
INBYTE=`cat ${MY_FIFO}`
echo The input byte is:
printf “${INBYTE}” | xxd -cols 1 | sed ‘s/^.*: //’
fi
done
kill ${READPID}
On the other one, I run:
Code:
printf ‘Hello, world!’ > INPUT
Then, back on the first terminal, I type ‘y’ to the prompt, to test the bytegrabbing. The problem is: instead of getting only 1 byte, I sometimes get 1, 2, 3, 4, 5 bytes. A typical session looks something like:
Code:
y: print next byte
n: don’t print next byte
q: quit
y
The input byte is:
48 H
65 e
y: print next byte
n: don’t print next byte
q: quit
y
The input byte is:
6c l
6c l
6f o
2c ,
20
77 w
y: print next byte
n: don’t print next byte
q: quit
But, what I want is something like:
Code:
y: print next byte
n: don’t print next byte
q: quit
y
The input byte is:
48 H
y: print next byte
n: don’t print next byte
q: quit
y
The input byte is:
65 e
y: print next byte
n: don’t print next byte
q: quit
The mystery is: Why does FIFO spit out 2 or 4 bytes at a time, if I am only writing ONE byte at each iteration of the loop??:
Code:
IFS=
tail -n 1 -f ${MY_INPUT} | while read -N 1 CHAR ; do
printf “${CHAR}” > ${MY_FIFO}
done
The code seems to work with a ‘sleep’ delay of 0.2 right after ‘printf “${CHAR}” > ${MY_FIFO}’. But… why?
In order for this script to be perfect, I would require it to ONLY use FIFOs: No ugly and slow hard-drive file buffers, please. And also, NO ugly time delays.
Another funny thing is how, when I run in one terminal:
Code:
( IFS= ; tail -f FIFO | while read -N 1 CHAR ; do printf “${CHAR}” | xxd -cols 1 ; printf ‘..n’ ; done )
And, from another, I do
Code:
printf ‘Hello, world!’ > FIFO
I get:
Code:
0000000: 48 H
..
0000000: 65 e
..
0000000: 6c l
..
0000000: 6c l
..
0000000: 6f o
..
0000000: 2c ,
..
0000000: 20
..
0000000: 77 w
..
0000000: 6f o
..
0000000: 72 r
..
0000000: 6c l
..
0000000: 64 d
..
0000000: 21 !
..
Which goes to show that ${CHAR} never stores more than 1 byte at any given time. If it did, the output would look more like:
Code:
0000000: 48 H
0000000: 65 e
0000000: 6c l
0000000: 6c l
..
0000000: 6f o
0000000: 2c ,
0000000: 20
..
0000000: 77 w
0000000: 6f o
0000000: 72 r
0000000: 6c l
0000000: 64 d
0000000: 21 !
..
So… my question is… basically: What is the deal with this FIFO glitch? If the problem is not in the loop, then: Where is it?
Source: The UNIX and Linux Forums