IPC via named pipe: Difference between revisions

Added FreeBASIC
(→‎{{header|C}}: Edit comment: OpenBSD blocks the whole process.)
(Added FreeBASIC)
 
(21 intermediate revisions by 12 users not shown)
Line 1:
{{draft task}}
[[wp:Named pipe|Named pipe]], or FIFO, is a way of providing inter-process communications (IPC). The Totask is to demonstrate how it works, create two pipes, say, "in" and "out" (choose suitable names for your system), and write a program that works the two pipes such that:
# Data written to the "in" FIFO will be discarded except the byte count, which will be added to a total tally kept by the program;
# Whenever another process reads the "out" FIFO, it should receive the total count so far.
Line 12:
=={{header|C}}==
{{libheader|pthread}}
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
Line 18:
#include <limits.h>
#include <pthread.h>
 
/* Flag for systems where a blocking open on a pipe will block
entire process instead of just current thread. Ideally this
kind of flags should be automatically probed, but not before
we are sure about how each OS behaves. It can be set to 1
even if not needed to, but that would force polling, which I'd
rather not do.
Linux: won't block all threads (0)
OpenBSD: will block all (1)
Other OSes: ?
*/
 
#define WILL_BLOCK_EVERYTHING 0
 
#if WILL_BLOCK_EVERYTHING
#include <poll.h>
#endif
 
size_t tally = 0;
Line 26 ⟶ 43:
char buf[32];
while (1) {
#if WILL_BLOCK_EVERYTHING
/* This will block current thread. On Linux it won't block
/* try to open non-block. sleep and retry if no reader */
the other thread (the reader). On OpenBSD it blocks the
fd = open("out", O_WRONLY|O_NONBLOCK);
whole process (causing problems), because of a bug in the
if (fd < thread0) library.{ /* Whatassume happensit's onENXIO, other"no OS?reader" */
usleep(200000);
continue;
}
#else
/* block open, until a reader comes along */
fd = open("out", O_WRONLY);
#endif
write(fd, buf, snprintf(buf, 32, "%d\n", tally));
close(fd);
Line 46 ⟶ 69:
size_t len;
char buf[PIPE_BUF];
#if WILL_BLOCK_EVERYTHING
struct pollfd pfd;
pfd.events = POLLIN;
#endif
while (1) {
#if WILL_BLOCK_EVERYTHING
fd = pfd.fd = open("in", O_RDONLY|O_NONBLOCK);
fcntl(fd, F_SETFL, 0); /* disable O_NONBLOCK */
poll(&pfd, 1, INFTIM); /* poll to avoid reading EOF */
#else
fd = open("in", O_RDONLY);
#endif
while ((len = read(fd, buf, PIPE_BUF))) tally += len;
while ((len = read(fd, buf, PIPE_BUF)) > 0) tally += len;
close(fd);
}
Line 69 ⟶ 102:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="vbnet">#Include "file.bi"
 
Type FileInfo
As String path
As Integer oflag
End Type
 
Function OpenFile(file As FileInfo) As Integer
Dim As Integer f = Freefile
Open file.path For Binary Access Read Write As #f
If Lof(f) > 0 Then
Print "Error opening file"
Return -1
End If
Return f
End Function
 
Function ReadFromFile(f As Integer, Byref buf As String, size As Integer) As Integer
Get #f, , buf
Return Len(buf)
End Function
 
Sub WriteToFile(f As Integer, buf As String, size As Integer)
Put #f, , buf
End Sub
 
Dim As FileInfo inputFile
inputFile.path = "in.fifo"
inputFile.oflag = 0
 
Dim As FileInfo outputFile
outputFile.path = "out.fifo"
outputFile.oflag = 1
 
Dim As Integer entrada = OpenFile(inputFile)
Dim As Integer salida = OpenFile(outputFile)
 
If entrada = -1 Or salida = -1 Then
Print "Error opening files"
End
End If
 
Dim As String buffer
Dim As Integer bytesRead
Do
bytesRead = ReadFromFile(entrada, buffer, 64)
If bytesRead > 0 Then WriteToFile(salida, buffer, bytesRead)
Loop</syntaxhighlight>
 
=={{header|Go}}==
<syntaxhighlight lang="go">package main
 
import (
"fmt"
"io"
"log"
"os"
"sync/atomic"
"syscall"
)
 
const (
inputFifo = "/tmp/in.fifo"
outputFifo = "/tmp/out.fifo"
readsize = 64 << 10
)
 
func openFifo(path string, oflag int) (f *os.File, err error) {
err = syscall.Mkfifo(path, 0660)
// We'll ignore "file exists" errors and assume the FIFO was pre-made
if err != nil && !os.IsExist(err) {
return
}
f, err = os.OpenFile(path, oflag, 0660)
if err != nil {
return
}
// In case we're using a pre-made file, check that it's actually a FIFO
fi, err := f.Stat()
if err != nil {
f.Close()
return nil, err
}
if fi.Mode()&os.ModeType != os.ModeNamedPipe {
f.Close()
return nil, os.ErrExist
}
return
}
 
func main() {
var byteCount int64
go func() {
var delta int
var err error
buf := make([]byte, readsize)
for {
input, err := openFifo(inputFifo, os.O_RDONLY)
if err != nil {
break
}
for err == nil {
delta, err = input.Read(buf)
atomic.AddInt64(&byteCount, int64(delta))
}
input.Close()
if err != io.EOF {
break
}
}
log.Fatal(err)
}()
 
for {
output, err := openFifo(outputFifo, os.O_WRONLY)
if err != nil {
log.Fatal(err)
}
cnt := atomic.LoadInt64(&byteCount)
fmt.Fprintln(output, cnt)
output.Close()
}
}</syntaxhighlight>
 
=={{header|Perl}}==
{{trans|Raku}}
<syntaxhighlight lang="perl"># 20200924 added Perl programming solution
 
use strict;
use warnings;
 
use File::Temp qw/ :POSIX /;
use POSIX qw/ mkfifo /;
use Fcntl;
 
my ($in, $out) = map { scalar tmpnam() } 0,1 ;
 
for ($in, $out) { mkfifo($_,0666) or die $! };
 
print "In pipe : $in\nOut pipe : $out\n";
 
my $CharCount = 0 ;
 
$SIG{INT} = sub {
for ($in, $out) { unlink $_ or die }
print "\nTotal Character Count: $CharCount\nBye.\n" and exit
};
 
sysopen( IN, $in, O_NONBLOCK|O_RDONLY ) or die;
sysopen( OUT, $out, O_NONBLOCK|O_RDWR ) or die;
 
while (1) {
sysread(IN, my $buf, 32); # borrowed the buffer size from the c entry
if ( length $buf > 0 ) {
$CharCount += length $buf;
while (sysread(OUT, $buf, 1)) {} ; # empty the write pipe
syswrite( OUT, $CharCount ) or die;
}
sleep .5;
}</syntaxhighlight>
{{out}}
Terminal 1
<pre>In pipe : /tmp/0oPaYmkOI2
Out pipe : /tmp/DdWOGVOaBI
^C
Total Character Count: 7083641
Bye.</pre>
Terminal 2
<pre>echo asdf > /tmp/0oPaYmkOI2
cat /tmp/DdWOGVOaBI
5^C
echo qwer > /tmp/0oPaYmkOI2
echo uiop > /tmp/0oPaYmkOI2
cat /tmp/DdWOGVOaBI
15^C
wc /etc/passwd
33 63 1642 /etc/passwd
cat /etc/passwd > /tmp/0oPaYmkOI2
cat /tmp/DdWOGVOaBI
1657^C
cat /dev/urandom > /tmp/0oPaYmkOI2
^C
cat /tmp/DdWOGVOaBI
7083641^C</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\IPC_via_named_pipe.exw
-- ===================================
--
-- Note: uses a single bidirectional pipe, Windows only, and no attempt has been
-- made to avoid blocking, this sort of code should be put in a separate thread.
--
-- Running normally starts this as a server which automatically creates a client.
--
-- Several additional Windows-only routines have been added to builtins/pipeio.e
-- which will not be formally documented until they are fully Linux-compatible.
--</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1.0.1"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #004600;">WINDOWS</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (obviously this will never ever run in a browser!)</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">/</span><span style="color: #000000;">pipeio</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">szPipename</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">`\\.\pipe\mynamedpipe`</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">cl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">command_line</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">rand_string</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rand_range</span><span style="color: #0000FF;">(</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'Z'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"-client"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Server\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">dwPipeMode</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">or_all</span><span style="color: #0000FF;">({</span><span style="color: #000000;">PIPE_TYPE_MESSAGE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PIPE_READMODE_MESSAGE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PIPE_WAIT</span><span style="color: #0000FF;">}),</span>
<span style="color: #000000;">totalsofar</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">pBuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">pBytesRead</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">pBytesWritten</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">hPipe</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">create_named_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">szPipename</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PIPE_ACCESS_DUPLEX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dwPipeMode</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">system_exec</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">`"%s" "%s" -client`</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cl</span><span style="color: #0000FF;">),</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">connect_named_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">read_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBuffer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1024</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBytesRead</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">res</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nsleep??\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.25</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bytesread</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peek4s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pBytesRead</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">peek</span><span style="color: #0000FF;">({</span><span style="color: #000000;">pBuffer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bytesread</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bytesread</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">and</span> <span style="color: #000000;">msg</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"quit"</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nquit recieved, quitting\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">totalsofar</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">bytesread</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"bytesread:%,d total so far:%,d "</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">bytesread</span><span style="color: #0000FF;">,</span><span style="color: #000000;">totalsofar</span><span style="color: #0000FF;">})</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">reply</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%,d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">totalsofar</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">write_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">,</span><span style="color: #000000;">reply</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBytesWritten</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">res</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">peek4s</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pBytesWritten</span><span style="color: #0000FF;">)!=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">reply</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">flush_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">disconnect_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">free</span><span style="color: #0000FF;">({</span><span style="color: #000000;">pBytesWritten</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBuffer</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pBytesRead</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">close_handle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Client\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Press Escape or Q to quit\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">running_total</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">get_key</span><span style="color: #0000FF;">(),{</span><span style="color: #008000;">'q'</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'Q'</span><span style="color: #0000FF;">,</span><span style="color: #000000;">#1B</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">msg</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rand_string</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">reply</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">call_named_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">szPipename</span><span style="color: #0000FF;">,</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">running_total</span> <span style="color: #0000FF;">+=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">bOK</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">reply</span><span style="color: #0000FF;">==</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%,d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">running_total</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">progress</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"set %d bytes, reply:%s, running_total:%,d (same:%t)"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">msg</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">reply</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">running_total</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bOK</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">bOK</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nsome error, quitting...\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">call_named_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">szPipename</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"quit"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
{{out}}
After letting it run for about 5s before hitting escape, on separate terminal windows:
<pre>
Server
bytesread:19 total so far:2,136,798
quit recieved, quitting
 
Client
Press Escape or Q to quit
set 19 bytes, reply:2,136,798, running_total:2,136,798 (same:true)
</pre>
 
 
=={{header|PicoLisp}}==
<syntaxhighlight lang="picolisp">(call 'mkfifo "in" "out") # Create pipes
 
(zero *Cnt) # Initialize byte counter
 
(unless (fork) # Handle "out" pipe
(loop
(out "out"
(sync)
(tell)
(prinl *Cnt) ) ) )
 
(unless (fork) # Handle "in" pipe
(let P (open "in")
(loop
(in P # Open twice, to avoid broken pipes
(while (rd 1) # (works on Linux, perhaps not POSIX)
(tell 'inc ''*Cnt) ) ) ) ) )
 
(push '*Bye '(call 'rm "in" "out")) # Remove pipes upon exit
(wait) # (Terminate with Ctrl-C)</syntaxhighlight>
Test:
<pre>$ line <out
0
$ echo abc >in
$ line <out
4
$ echo äöü >in
$ line <out
11</pre>
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">#lang racket
 
(define-values (in out) (make-pipe))
 
;; Thread loops through list of strings to send
;; and closes port when finished
(define t1 (thread (lambda ()
(for ([i (list "a" "test" "sequence")])
(display i out)
(sleep 1))
(close-output-port out))))
 
;; Blocking call to read char, if not EOF then loop
(define t2 (thread (lambda ()
(define cnt 0)
(let loop ()
(when (not (eof-object? (read-char in)))
(set! cnt (add1 cnt))
(loop)))
(display (format "Bytes Rx: ~a\n" cnt))
(close-input-port in))))
 
(thread-wait t1)
(thread-wait t2)</syntaxhighlight>
 
=={{header|Raku}}==
{{incorrect|Raku| Blocks on the read pipe and not able to empty/update the write pipe according to the task requirement }}
Couldn't figure out how to get around the IO blockages as per the talk page so any help would be appreciated, thanks in advance.
<syntaxhighlight lang="raku" line># 20200923 Added Raku programming solution
 
use NativeCall;
use UUID; # cannot mix File::Temp with mkfifo well so use this as tmpnam
 
my ($in, $out) = <in out>.map: { "/tmp/$_-" ~ UUID.new } ;
 
sub mkfifo(Str $pathname, int32 $mode --> int32) is native('libc.so.6') is symbol('mkfifo') {*}
 
($in,$out).map: { die $!.message if mkfifo($_, 0o666) } ; # c style exit code
 
say "In pipe: ", $in;
say "Out pipe: ", $out;
 
my atomicint $CharCount = 0;
 
signal(SIGINT).tap: {
($in,$out).map: { .IO.unlink or die } ;
say "\nBye." and exit;
}
 
loop {
given $in.IO.watch { # always true even when nothing is spinning ?
 
say "Current count: ", $CharCount ⚛+= $in.IO.open.readchars.codes;
 
given $out.IO.open(:update :truncate) { # both truncate and flush aren't
.flush or die ; # working on pipes so without a
.spurt: "$CharCount\t" # prior consumer it just appends
}
$out.IO.open.close or die;
}
sleep ½;
}</syntaxhighlight>
{{out}}
Terminal 1
<pre>named-pipe.raku
In pipe: /tmp/in-b49e4cdf-80b6-49da-b4a3-2810f1eeeb6a
Out pipe: /tmp/out-44fcd0db-ce02-47b4-bdd3-34833f3dd621
Current count: 5
Current count: 10
Current count: 15
^C
Bye.</pre>
Terminal 2
<pre>echo asdf > /tmp/in-b49e4cdf-80b6-49da-b4a3-2810f1eeeb6a
cat /tmp/out-44fcd0db-ce02-47b4-bdd3-34833f3dd621
5 ^C
echo qwer > /tmp/in-b49e4cdf-80b6-49da-b4a3-2810f1eeeb6a
echo uiop > /tmp/in-b49e4cdf-80b6-49da-b4a3-2810f1eeeb6a
cat /tmp/out-44fcd0db-ce02-47b4-bdd3-34833f3dd621
10 15 ^C</pre>
 
=={{header|Ruby}}==
Line 81 ⟶ 509:
{{works with|Unix}}
 
<langsyntaxhighlight lang="ruby">require 'socket'
 
# Ruby has no direct access to mkfifo(2). We use a shell script.
Line 141 ⟶ 569:
end
end
end</langsyntaxhighlight>
 
Example run:
Line 159 ⟶ 587:
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl"># Make the pipes by calling a subprocess...
exec sh -c {test -p in || mkfifo in || exit 1;test -p out || exec mkfifo out}
 
Line 190 ⟶ 618:
 
# Run the event loop until done
vwait forever</langsyntaxhighlight>
 
=={{header|Wren}}==
{{trans|C}}
{{libheader|pthread}}
An embedded program using a C host as Wren has no built in support for named pipes.
 
As in the case of the C example, we run the 'write' loop on a separate thread and using a separate VM. The 'tally' variable is stored on the C side so it can be shared by both VM's.
 
This works fine on Ubuntu 20.04 and should work on other Linux distros though I can't vouch for anything else.
<syntaxhighlight lang="wren">/* IPC_via_named_pipe.wren */
 
var InputFifo = "in"
var OutputFifo = "out"
 
var O_RDONLY = 0
var O_WRONLY = 1
 
var PIPE_BUF = 4096
 
class Fifo {
foreign static make(path, oflag)
}
 
class File {
foreign static open(path, flags)
 
foreign static write(fd, str, size)
 
foreign static read(fd, size)
 
foreign static close(fd)
}
 
class C {
foreign static usleep(usec)
 
foreign static tally
foreign static tally=(newTally)
}
 
class Loops {
static read() {
while (true) {
var fd = File.open(InputFifo, O_RDONLY)
var len
while ((len = File.read(fd, PIPE_BUF)) > 0) C.tally = C.tally + len
File.close(fd)
}
}
 
static write() {
while (true) {
var fd = File.open(OutputFifo, O_WRONLY)
var ts = C.tally.toString + "\n"
File.write(fd, ts, ts.bytes.count)
File.close(fd)
C.usleep(10000)
}
}
}
 
Fifo.make(InputFifo, 438)
Fifo.make(OutputFifo, 438)</syntaxhighlight>
<br>
We now embed this script in the following C program, build and run from one terminal.
<syntaxhighlight lang="c">/* gcc IPC_via_named_pipe.c -o IPC_via_named_pipe -lpthread -lwren -lm */
 
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include "wren.h"
 
/* C <=> Wren interface functions */
 
size_t tally = 0;
 
void C_make(WrenVM* vm) {
const char *pathname = wrenGetSlotString(vm, 1);
mode_t mode = (mode_t)wrenGetSlotDouble(vm, 2);
int res = mkfifo(pathname, mode);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_open(WrenVM* vm) {
const char *pathname = wrenGetSlotString(vm, 1);
int flags = (int)wrenGetSlotDouble(vm, 2);
int fd = open(pathname, flags);
if (fd < 0) {
perror(NULL);
}
wrenSetSlotDouble(vm, 0, (double)fd);
}
 
void C_write(WrenVM* vm) {
int fd = (int)wrenGetSlotDouble(vm, 1);
const char *str = wrenGetSlotString(vm, 2);
size_t count = (size_t)wrenGetSlotDouble(vm, 3);
ssize_t res = write(fd, (const void *)str, count + 1);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_read(WrenVM* vm) {
int fd = (int)wrenGetSlotDouble(vm, 1);
size_t nbyte = (size_t)wrenGetSlotDouble(vm, 2);
char buf[nbyte];
ssize_t res = read(fd, buf, nbyte);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_close(WrenVM* vm) {
int fd = (int)wrenGetSlotDouble(vm, 1);
int res = close(fd);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_usleep(WrenVM* vm) {
useconds_t usec = (useconds_t)wrenGetSlotDouble(vm, 1);
int res = usleep(usec);
wrenSetSlotDouble(vm, 0, (double)res);
}
 
void C_getTally(WrenVM* vm) {
wrenSetSlotDouble(vm, 0, (double)tally);
}
 
void C_setTally(WrenVM* vm) {
size_t newTally = (size_t)wrenGetSlotDouble(vm, 1);
tally = newTally;
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "Fifo") == 0) {
if (isStatic && strcmp(signature, "make(_,_)") == 0) return C_make;
} else if (strcmp(className, "File") == 0) {
if (isStatic && strcmp(signature, "open(_,_)") == 0) return C_open;
if (isStatic && strcmp(signature, "write(_,_,_)") == 0) return C_write;
if (isStatic && strcmp(signature, "read(_,_)") == 0) return C_read;
if (isStatic && strcmp(signature, "close(_)") == 0) return C_close;
} else if (strcmp(className, "C") == 0) {
if (isStatic && strcmp(signature, "usleep(_)") == 0) return C_usleep;
if (isStatic && strcmp(signature, "tally") == 0) return C_getTally;
if (isStatic && strcmp(signature, "tally=(_)") == 0) return C_setTally;
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
 
WrenVM *vm, *vm2;
 
void read_loop() {
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "main", "Loops", 0);
WrenHandle *method = wrenMakeCallHandle(vm, "read()");
wrenCall(vm, method);
wrenReleaseHandle(vm, method);
}
 
void* write_loop(void *a) {
wrenEnsureSlots(vm2, 1);
wrenGetVariable(vm2, "main", "Loops", 0);
WrenHandle *method = wrenMakeCallHandle(vm2, "write()");
wrenCall(vm2, method);
wrenReleaseHandle(vm2, method);
}
 
int main(int argc, char **argv) {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignMethodFn = &bindForeignMethod;
vm = wrenNewVM(&config);
vm2 = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "IPC_via_named_pipe.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenInterpret(vm2, module, script);
pthread_t pid;
pthread_create(&pid, 0, write_loop, 0);
read_loop();
wrenFreeVM(vm);
wrenFreeVM(vm2);
free(script);
return 0;
}</syntaxhighlight>
<br>
{{out}}
Finally we can test that this is working correctly by typing in the following commands from a different terminal. The string lengths returned will, of course, include the final zero byte.
<pre>
$ cat out
0
$ echo test > in
$ cat out
5
$ echo "named pipe" > in
$ cat out
16
</pre>
 
=={{header|zkl}}==
zkl doesn't open pipes but it knows about them (on Unix anyway as they are just a file). So, outside of the program, create two named pipes and read/write to them inside the program.
{{trans|C}}
<syntaxhighlight lang="zkl">pipe:=Thread.Pipe(); // NOT a Unix pipe, for inter-thread commication
fcn writeLoop(pipe){ // a thread
out:=File("out","w");
foreach tally in (pipe){ out.writeln(tally); out.flush(); }
println("writeLoop done");
}.launch(pipe);
 
fcn readLoop(pipe){ // a thread
tally:=0;
in:=File("in","r").howza(3); // open for read, reading characters
while(1){ // named pipe sets EoF after writer exits
foreach c in (in){ pipe.write(tally+=1) } // read bytes until EoF
}
in.close();
println("readLoop done");
}.launch(pipe);
 
while(1){ Atomic.sleep(10000); } // veg out while other talk</syntaxhighlight>
{{out}}
Terminal 1:
<pre>
$ mkfifo in; mkfifo out
<wait until other two terminals get going>
$ echo "hello world" > in
$ cat ../Tests/lorem_ipsum.txt >in
</pre>
{{out}}
In Terminal 2, start the program:
<pre>$ zkl bbb</pre>
{{out}}
Terminal 3:
There is pretty much no delay - character enters "in", "out" sees tally.
<pre>
$ cat out
1
2
3
4
5
6
7
8
9
10
11
12
...
1391
1392
1393
1394
1395
1396
1397
1398
1399
</pre>
 
{{omit from|GUISS}}
{{omit from|Mathematica}}
{{omit from|ZX Spectrum Basic}}
2,122

edits