Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Mental-model of multiprocessing?

8 views
Skip to first unread message

Avoi...@gmail.com

unread,
Mar 27, 2013, 7:13:30 AM3/27/13
to
For someone who knows the stacked-subroutine-calling mechanism
[down to the silicon level], and resists the little-men-in-the-box
mental model, it's difficult to UNDERSTAND how to build a script that:
calls a URL via openssl,
conducts a dialog with the remote server,
and saves the log of the process in a file.
--
My main difficulty seems to be that apparently the 'routines'
are NOT stacked:
User's shell > Script > openssl > REPEAT{dialog; log}.
The dialog-steps must be <WRAPPED> in the openssl.

How does openssl know when to <return>?

Here's a snipppet of related script which I don't understand:---
# Author Pascal B..
local_name=localhost
if [ "$1" = "--log" ] ; then shift ; trace=echo ; else trace=true ; fi
log=/dev/tty
message=/tmp/message.$$
cat>$message
(
read line 0<&3 ; $trace "$line">$log
case "$line" in 2*) ;; *) echo "QUIT" 1>&3 ; exit 0 ;; esac
echo "HELO $local_name" 1>&3
read line 0<&3 ; $trace "$line">$log
case "$line" in 2*) ;; *) echo "QUIT" 1>&3 ; exit 0 ;; esac
echo "MAIL FROM: <${from}>" 1>&3
...
echo "QUIT" 1>&3
) 3<>/dev/tcp/$smtp_server/25
==== end of script snippet

What's the meaning of:
cat>/tmp/mesgFile
(
read line 0<&3 ; echo "$line">$log
case "$line" in 2*) ;; *) echo "QUIT" 1>&3 ; exit 0 ;; esac
echo "HELO $local_name" 1>&3
) 3<>/dev/tcp/$smtp_server/25
??!

Where's to doco/man for the syntax:-
cat>/File
( <read; select; write> ) 3<>/dev/tcp/URL/PORT
??!

How is data read from /dev/tty ?

# echo dog > /dev/tty
# cat /dev/tty
# echo dog > /dev/tty ; cat /dev/tty
give unexpected results FOR ME

/dev/tty seems to behave like $1 AND like $2 ?!?

Apparently my confusion is about 'redirection' ?

So, where's a good mental-model of multiprocessing,
documented?

Thanks for any pointers/explanations.

Joe Beanfish

unread,
Mar 27, 2013, 10:02:47 AM3/27/13
to
On Wed, 27 Mar 2013 11:13:30 +0000, Avoid9Pdf wrote:
> For someone who knows the stacked-subroutine-calling mechanism [down to
> the silicon level], and resists the little-men-in-the-box mental model,
> it's difficult to UNDERSTAND how to build a script that:
> calls a URL via openssl,
> conducts a dialog with the remote server,
> and saves the log of the process in a file.
> --
> My main difficulty seems to be that apparently the 'routines'
> are NOT stacked:

Correct, they all run at the "same" time. See below.

> User's shell > Script > openssl > REPEAT{dialog; log}.
>
> What's the meaning of:
> cat>/tmp/mesgFile

Read from stdin and write that to mesgFile.

> (

Commands inside parens are run in another shell.

> read line 0<&3 ; echo "$line">$log case "$line" in 2*) ;; *) echo
> "QUIT" 1>&3 ; exit 0 ;; esac echo "HELO $local_name" 1>&3

Read from file-descriptor 3 into variable line. Log it.
If it starts with anything but 2 write QUIT to file-descriptor 3 and exit.
write "HELO .." to file-descriptor 3.

> ) 3<>/dev/tcp/$smtp_server/25 ??!

Set file-descriptor 3 to read/write the specified device.

> Where's to doco/man for the syntax:-
> cat>/File ( <read; select; write> ) 3<>/dev/tcp/URL/PORT ??!

Those (>, <, <>, read, case) are all shell (bash) constructs, so in
the bash manual.

> How is data read from /dev/tty ?
>
> # echo dog > /dev/tty # cat /dev/tty # echo dog > /dev/tty ; cat
> /dev/tty give unexpected results FOR ME

/dev/tty is an alias for your "terminal". Remember that an ssh or telnet
shell session is essentially like a console session which is a glass tty.
Reading (cat) from a tty takes input from the "keyboard". Writing to a tty
displays the output on the "screen".

> So, where's a good mental-model of multiprocessing,
> documented?

For the real thing instead of a model how about
"Design of the Unix operating system" by Maurice J. Bach.
Chapter 5.12 for Pipes. Chapters 6-8 for processes.

*Quick* overview of preemptive multitasking (glossing over MANY details):
The kernel loads N programs and lets each one run for a small slice of
time. Then it suspends the running one, and lets another run for a slice,
and so on many times a second. So it *appears* that they are all running
at the same time. This way programs can interact with each other without
one having to run to completion first. It also allows one program to sit
and wait for something, like disk or user input, without holding up all
the other programs that are also running.

Given the [silly] shell command
echo "Hello World" | cat >foo
the shell tells the kernel to run programs "echo" and "cat" with the
standard-output(stdout) of echo connected to the standard-input(stdin)
of cat (see pipe(2) and pipe(7)). And the standard output of cat
connected to file "foo". So when cat reads it's stdin it will see "Hello
World" and dutifully write that to it's standard-output. Upon trying to
read more it will find nothing, because echo didn't print more, and
therefore quit. The result will be "Hello World" in the file foo.

HTH

Richard Kettlewell

unread,
Mar 27, 2013, 10:13:48 AM3/27/13
to
Joe Beanfish <joebe...@nospam.duh> writes:
> *Quick* overview of preemptive multitasking (glossing over MANY details):
> The kernel loads N programs and lets each one run for a small slice of
> time. Then it suspends the running one, and lets another run for a slice,
> and so on many times a second. So it *appears* that they are all running
> at the same time. This way programs can interact with each other without
> one having to run to completion first. It also allows one program to sit
> and wait for something, like disk or user input, without holding up all
> the other programs that are also running.

NB that on modern systems there’s a good chance that the concurrency is
real, not (just) simulated through time-slicing. In shell programming
this makes little practical difference; in (for instance) C the
implications rather are more interesting.

--
http://www.greenend.org.uk/rjk/

The Natural Philosopher

unread,
Mar 27, 2013, 10:35:39 AM3/27/13
to
On 27/03/13 14:13, Richard Kettlewell wrote:
> Joe Beanfish <joebe...@nospam.duh> writes:
>> *Quick* overview of preemptive multitasking (glossing over MANY details):
>> The kernel loads N programs and lets each one run for a small slice of
>> time. Then it suspends the running one, and lets another run for a slice,
>> and so on many times a second. So it *appears* that they are all running
>> at the same time. This way programs can interact with each other without
>> one having to run to completion first. It also allows one program to sit
>> and wait for something, like disk or user input, without holding up all
>> the other programs that are also running.
>
> NB that on modern systems there’s a good chance that the concurrency is
> real, not (just) simulated through time-slicing.

you mean there are multiple cores running different processes in
different RAM spaces?

Fancy giving an overview of that? to add to the interest?



In shell programming
> this makes little practical difference; in (for instance) C the
> implications rather are more interesting.
>
I haven't looked at C stuff at that level - are their calls to spin
threads into different cores available?

I had assumed that the kernel itself would allocate CPUs to active
tasks, on the basis of whichever CPU had less going on, but not that a
given user level program would be able to control that ..




--
Ineptocracy

(in-ep-toc’-ra-cy) – a system of government where the least capable to
lead are elected by the least capable of producing, and where the
members of society least likely to sustain themselves or succeed, are
rewarded with goods and services paid for by the confiscated wealth of a
diminishing number of producers.

Chris Davies

unread,
Mar 27, 2013, 11:30:53 AM3/27/13
to
In comp.os.linux.misc The Natural Philosopher <t...@invalid.invalid> wrote:
> I haven't looked at C stuff at that level - are their calls to spin
> threads into different cores available?

Yes.


> I had assumed that the kernel itself would allocate CPUs to active
> tasks, on the basis of whichever CPU had less going on, but not that a
> given user level program would be able to control that ..

$ man -k affinity
pthread_attr_getaffinity_np (3) - set/get CPU affinity attribute in thread attributes object
pthread_attr_setaffinity_np (3) - set/get CPU affinity attribute in thread attributes object
pthread_getaffinity_np (3) - set/get CPU affinity of a thread
pthread_setaffinity_np (3) - set/get CPU affinity of a thread
sched_getaffinity (2) - set and get a process's CPU affinity mask
sched_setaffinity (2) - set and get a process's CPU affinity mask
taskset (1) - retrieve or set a process's CPU affinity

Chris

The Natural Philosopher

unread,
Mar 27, 2013, 2:57:12 PM3/27/13
to
now that will be stored in these vintage memory banks in case its handy
one day.

Thank you.

Richard Kettlewell

unread,
Mar 27, 2013, 5:15:07 PM3/27/13
to
The Natural Philosopher <t...@invalid.invalid> writes:
> Richard Kettlewell wrote:
>> Joe Beanfish <joebe...@nospam.duh> writes:

>>> *Quick* overview of preemptive multitasking (glossing over MANY
>>> details): The kernel loads N programs and lets each one run for a
>>> small slice of time. Then it suspends the running one, and lets
>>> another run for a slice, and so on many times a second. So it
>>> *appears* that they are all running at the same time. This way
>>> programs can interact with each other without one having to run to
>>> completion first. It also allows one program to sit and wait for
>>> something, like disk or user input, without holding up all the other
>>> programs that are also running.
>>
>> NB that on modern systems there’s a good chance that the concurrency
>> is real, not (just) simulated through time-slicing.
>
> you mean there are multiple cores running different processes in
> different RAM spaces?

Yes. Strictly, different virtual memory address spaces. Also, multiple
threads of a single process running on different cores but sharing
virtual memory.

> Fancy giving an overview of that? to add to the interest?

I’m not sure there’s much to say: it’s the same as SMP always was, but
now you get multiple cores[1] on a single die and it happens on
computers all the way down to smartphones and netbooks, not just hugely
expensive machines.

[1] Or parts of cores; exactly what is shared and what is duplicated
varies.

>> In shell programming this makes little practical difference; in (for
>> instance) C the implications rather are more interesting.
>
> I haven't looked at C stuff at that level - are their calls to spin
> threads into different cores available?
>
> I had assumed that the kernel itself would allocate CPUs to active
> tasks, on the basis of whichever CPU had less going on, but not that a
> given user level program would be able to control that ..

It’s possible to bind a particular thread (or process) to a particular
core. Whether it’s actually worthwhile depends on the task at hand.

But what I was alluding to is that caches aren’t completely transparent.
The immediate practical implication of this is that sequential
consistency is no longer preserved. A multi-threaded program written
assuming that it is, or even without that assumption as such but only
previously tested on a single-core system, is likely to misbehave on a
multi-core system.

http://en.wikipedia.org/wiki/Memory_ordering discusses.

--
http://www.greenend.org.uk/rjk/

The Natural Philosopher

unread,
Mar 27, 2013, 5:36:09 PM3/27/13
to
thanks for that. Not issues I have to deal with, but you never know.

Jorgen Grahn

unread,
Mar 27, 2013, 5:47:33 PM3/27/13
to
["Followup-To:" header set to comp.os.linux.misc.]

On Wed, 2013-03-27, Richard Kettlewell wrote:
...
> NB that on modern systems there's a good chance that the concurrency is
> real, not (just) simulated through time-slicing. In shell programming
> this makes little practical difference; in (for instance) C the
> implications rather are more interesting.

The difference is sometimes practical in shell programming, too; a
pipeline may run significantly faster, if it's CPU-bound in more than
one place. This has mattered to me in some real scenarios.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Aragorn

unread,
Mar 28, 2013, 1:56:57 AM3/28/13
to
On Wednesday 27 March 2013 22:15, Richard Kettlewell conveyed the
following to comp.os.linux.misc...

> It’s possible to bind a particular thread (or process) to a particular
> core. Whether it’s actually worthwhile depends on the task at hand.
>
> But what I was alluding to is that caches aren’t completely
> transparent. The immediate practical implication of this is that
> sequential consistency is no longer preserved. A multi-threaded
> program written assuming that it is, or even without that assumption
> as such but only previously tested on a single-core system, is likely
> to misbehave on a multi-core system.
>
> http://en.wikipedia.org/wiki/Memory_ordering discusses.

And it gets even more complicated with NUMA. The AMD-proper
implementations of AMD64 were conceived from the ground up as (cc)NUMA -
for Intel, it took them up until the i7 architecture before they started
integrating the memory controller on the processor die.

--
= Aragorn =

http://www.linuxcounter.net - registrant #223157

Avoi...@gmail.com

unread,
Mar 29, 2013, 10:28:08 AM3/29/13
to
In article <kiuu67$4lv$1...@dont-email.me>, Joe Beanfish <joebe...@nospam.duh> wrote:

> On Wed, 27 Mar 2013 11:13:30 +0000, Avoid9Pdf wrote:

Thanks to Joe Beanfish for a competent explanation, but I've still got plenty
queries. My problem with the design of bash is subtle. Which is why noone
else raises it? They just keep their head down and march on.

A child can LEARN to parse the 4 word-sentence:
"Mis he will understand";
but only by considering the WHOLE sentence, BEFORE starting to parse;
so that it's seen that "Mis" is not resolved until "understand" is read.

In 'proper' languages [the algol-family, which probably includes C], we
handle this simply by stacking [where lisp is the extreme/obvious example].

So: REPEAT <lotaStuff> UNTIL <boolean>
is no problem, since the parser knows to stack/push "REPEAT" until the
<lotaStuff> is resolved and then 'continue'.

But for the 5 line script:----
cat>/tmp/mesgFile
( echo 'Read from stdin and write that to mesgFile'
echo 'Commands inside parens are run in another shell'
echo 'Set file-descriptor 3 to read/write the specified device'
) 3<>/dev/tcp/$smtp_server/25

Apparently line1 is complete/resolvable?
Line2 can't resolve until line5's closing-parens?
Line5 resolves line2 AND sets file-descriptor 3?

Is that right ?
If so, then the complete script must be COMPILED, and can't be interpreted
and run one-line-at-a-time ?
-- snip ---
> Given the [silly] shell command
> echo "Hello World" | cat >foo
> the shell tells the kernel to run programs "echo" and "cat" with the
> standard-output(stdout) of echo connected to the standard-input(stdin)
> of cat (see pipe(2) and pipe(7)). And the standard output of cat
> connected to file "foo". So when cat reads it's stdin it will see "Hello
> World" and dutifully write that to it's standard-output. Upon trying to
> read more it will find nothing, because echo didn't print more, and
> therefore quit. The result will be "Hello World" in the file foo.
>
That convolution completely throws me!
Here's how I've MIS-learned it.
echo "Hello World"
== puts "Hello World" to standard-out
> foo
== redirects the [output to standard-out] to device: foo

And I've always understood `cat` to be equivqlent to:
outport(PortNo, byte) in machime code; OR
Write(device, ByteString); with the distortion/morphing
that device = stdout, when omitted.

Then I find that NO! according to a deeper read of the man:
"Concatenate FILE(s), or standard input, to standard output."
Which means it's something like:-
IF args=Nill THEN print(keybrd)
ELSE ForAllArgsDO{
IF arg="-" THEN print(keybrd)
ELSE print(argN)
}

But even that's not enough!
You've come with a NEW syntax apparently undocumented
in `man cat`:-
] echo "Hello World" | cat >foo
where the input/argument doesn't appear after the 'verb'.

But the syntax of cat was determined independant and before
shell-redirection, so the shell should TAKE the existing syntax
and use that.

How does the shell morph the syntax of `cat`?!
This looks like FRAUD!! Where's the FBI?


The Natural Philosopher

unread,
Mar 29, 2013, 11:32:15 AM3/29/13
to

> How does the shell morph the syntax of `cat`?!
> This looks like FRAUD!! Where's the FBI?
>
>
It looks like the irrelevant mndless drivel of someone who has stumbled
on an old building and is surprised to see a chimney in the middle of
it, since everyone now has central heating

Chris Davies

unread,
Mar 29, 2013, 1:31:39 PM3/29/13
to
In comp.os.linux.networking Avoi...@gmail.com wrote:
> How does the shell morph the syntax of `cat`?!
> This looks like FRAUD!! Where's the FBI?

It doesn't morph cat's syntax. You've maybe got an invalid mental model,
though.

Start with stdin "standard input" and stdout "standard output". Usually
the keyboard provides stdin (on file descriptor 0) and the screen/terminal
accepts stdout from file descriptor 1. There's also stderr on file
descriptor 2, but I'm going to ignore that.

All the default assignments can be changed with the < and > modifiers;
these work respectively on file descriptor 0 (stdin) and 1 (stdout)
unless you explicitly state otherwise.

Every standalone command is initially attached to stdin and stdout. The
"|" pipe symbol attaches the stdout from its left-hand side to the stdin
of the right-hand side. Brackets "(..)" group commands together into a
single unit.

The cat command is defined to concatentate one or more files provided
as command line parameters, or stdin if none is provided. It writes the
result to stdout.

Using these simplified rules you can see that this next command line
takes the stdout from echo and writes to the stdin of cat. Cat is defined
to send its inputs to stdout, and that isn't redirected anywhere so it
appears on your terminal.

echo "hello, world" | cat

Easy really.
Chris

Avoi...@gmail.com

unread,
Mar 29, 2013, 5:10:40 PM3/29/13
to
In article <rovg2ax...@news.roaima.co.uk>, Chris Davies <chris-...@roaima.co.uk> wrote:

> In comp.os.linux.networking Avoi...@gmail.com wrote:
> > How does the shell morph the syntax of `cat`?!
> > This looks like FRAUD!! Where's the FBI?
>
> It doesn't morph cat's syntax. You've maybe got an invalid mental model,
> though.
>
True, on your explanation, it merely wraps/extends the syntax
that the shell can use with `cat`. And apparently the key is your
statement:
> >Every standalone command is initially attached to stdin and stdout.
>
Good, we like universally applicable statements, instead of band-aids.
But what is eg. a NON-standalone command?
Are `<>` , `|` commands, and stand-alone ?

I'd always thought of `cat` as an 'originator': the first routine to
operate/fetch the data. Like `echo`. So the 1st operator in the
piped series has no predecessor.

Has `echo` got an 'input' too?
What's the definition of 'attached to'?
Has `pwd` also got a pipeable input?

> Using these simplified rules you can see that this next command line
> takes the stdout from echo and writes to the stdin of cat. Cat is defined
> to send its inputs to stdout, and that isn't redirected anywhere so it
> appears on your terminal.
>
> echo "hello, world" | cat
> Easy really.
>
Which you would never write [nor echo "hello" | cat | cat | cat ]
But the original code used THIS syntax, and that may be the key
to understanding the code. So then:
cat>/tmp/mesgFile
(
read line 0<&3 ; echo "$line">$log
case "$line" in 2*) ;; *) echo "QUIT" 1>&3 ; exit 0 ;; esac
echo "HELO $local_name" 1>&3
) 3<>/dev/tcp/$smtp_server/25

would mean
"stdin [since none is provided]" writeTo /tmp/mesgFile
the sequential output of the bracketed-statements
[which also write to there OWN destinations]
.... ??

Does: 3<>/dev/tcp/$smtp_server/25
mean: let fd3 have input AND output to that-device?

*THAT* is the 'fraud'(:-;) !!
Only AFTER it's been used is it defined.
Users who've not done asm-coding nor compilers, forth
would have no problem with the essential details being
written at the END of the contract.

Because I CAN ride a bicycle, doesn't mean I KNOW how
to ride one, nor that your dog KNOWS how to catch a ball.

Just-do-it is what they followed when they mortgaged their
houses for beer.

It would be good if the *nix docos put UP FRONT that
'it's not parsed sequentially left-to-right'; like computers
work or mathematical theorems are proved.

It works like poetry: you must get the whole picture
before interpreting.

Thanks for the input.

J G Miller

unread,
Mar 29, 2013, 6:36:42 PM3/29/13
to
On Friday, March 29th, 2013, at 15:32:15h +0000, The Natural Philosopher imagined:

> It looks like the irrelevant mndless drivel of someone who has stumbled
> on an old building and is surprised to see a chimney in the middle of
> it, since everyone now has central heating

No, not everyone has central heating, and chimney sweeps are still in business.

<http://www.gumtree.co.ZA/fp-chimney+sweep>

Example of chimneys on a bungalow in Balmoral Avenue, Arcadia, Pretoria
in the City of Tshwane.

<http://wiki.up.ac.ZA/images/b/ba/Pic_9.JPG>

Chris F.A. Johnson

unread,
Mar 29, 2013, 6:55:37 PM3/29/13
to
On 2013-03-29, Avoi...@gmail.com wrote:
...
> Has `echo` got an 'input' too?

Yes, but it doesn 't read it.

> What's the definition of 'attached to'?

'sends output to' or 'reads input from'

> Has `pwd` also got a pipeable input?

I*t's not 'pipeable', because it doesn 't read it.

>> Using these simplified rules you can see that this next command line
>> takes the stdout from echo and writes to the stdin of cat. Cat is defined
>> to send its inputs to stdout, and that isn't redirected anywhere so it
>> appears on your terminal.
>>
>> echo "hello, world" | cat
>> Easy really.
>>
> Which you would never write [nor echo "hello" | cat | cat | cat ]

But you could, and it would work.

> But the original code used THIS syntax, and that may be the key
> to understanding the code. So then:
> cat>/tmp/mesgFile
> (
> read line 0<&3 ; echo "$line">$log
> case "$line" in 2*) ;; *) echo "QUIT" 1>&3 ; exit 0 ;; esac
> echo "HELO $local_name" 1>&3
> ) 3<>/dev/tcp/$smtp_server/25
>
> would mean
> "stdin [since none is provided]" writeTo /tmp/mesgFile
> the sequential output of the bracketed-statements
> [which also write to there OWN destinations]
> .... ??
>
> Does: 3<>/dev/tcp/$smtp_server/25
> mean: let fd3 have input AND output to that-device?

Yes. Read the man page:

Opening File Descriptors for Reading and Writing
The redirection operator

[n]<>word

causes the file whose name is the expansion of word to be
opened for both reading and writing on file descriptor n, or on
file descriptor 0 if n is not specified. If the file does not
exist, it is created.


> *THAT* is the 'fraud'(:-;) !!
> Only AFTER it's been used is it defined.

The shell parses the line and sets up redirection before executing
the command.

...
> It would be good if the *nix docos put UP FRONT that
> 'it's not parsed sequentially left-to-right'; like computers
> work or mathematical theorems are proved.

It *is* explained in the man page.

> It works like poetry: you must get the whole picture
> before interpreting.

Yes, that's what the shell does.

--
Chris F.A. Johnson, <http://cfajohnson.com>
Author:
Pro Bash Programming: Scripting the GNU/Linux Shell (2009, Apress)
Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress)

Unknown

unread,
Mar 30, 2013, 2:01:39 AM3/30/13
to
On Fri, 29 Mar 2013 18:55:37 -0400, Chris F.A. Johnson wrote:

> On 2013-03-29, Avoi...@gmail.com wrote: ...

>>> Using these simplified rules you can see that this next command line
>>> takes the stdout from echo and writes to the stdin of cat. Cat is
>>> defined to send its inputs to stdout, and that isn't redirected
>>> anywhere so it appears on your terminal.
>>>
>>> echo "hello, world" | cat
>>> Easy really.
>>>
>> Which you would never write [nor echo "hello" | cat | cat | cat ]
>
> But you could, and it would work.
>
Why can't *ANYBODY* pickup the vital clue that Pascal Bourguignon's
script's analysis lies in WHY you would write: echo "hello" | cat
instead of: echo "hello"

It's obviously NEEDED to handle the convoluted: user talks to script,
talks to server, talks to log .....

>> But the original code used THIS syntax, and that may be the key to
>> understanding the code. So then:
>> cat>/tmp/mesgFile
>> (
>> read line 0<&3 ; echo "$line">$log
>> case "$line" in 2*) ;; *) echo "QUIT" 1>&3 ; exit 0 ;; esac echo
>> "HELO $local_name" 1>&3
>> ) 3<>/dev/tcp/$smtp_server/25
>>
>> would mean
>> "stdin [since none is provided]" writeTo /tmp/mesgFile the sequential
>> output of the bracketed-statements [which also write to there OWN
>> destinations] .... ??
>>
>> Does: 3<>/dev/tcp/$smtp_server/25
>> mean: let fd3 have input AND output to that-device?
>
> Yes. Read the man page:
>
My immediately above query asks 2 questions. Only the last, easy one is
answered.

> Opening File Descriptors for Reading and Writing
> The redirection operator
>
> [n]<>word
>
> causes the file whose name is the expansion of word to be opened
> for both reading and writing on file descriptor n, or on file
> descriptor 0 if n is not specified. If the file does not exist,
> it is created.
>
>
>> *THAT* is the 'fraud'(:-;) !!
>> Only AFTER it's been used is it defined.
>
> The shell parses the line and sets up redirection before executing
> the command.
>
> ...
>> It would be good if the *nix docos put UP FRONT that 'it's not parsed
>> sequentially left-to-right'; like computers work or mathematical
>> theorems are proved.
>
> It *is* explained in the man page.
>
>> It works like poetry: you must get the whole picture before
>> interpreting.
>
> Yes, that's what the shell does.

In this case, the script is about 50 lines; but it could be 50050;
and to go back to my opening observation of the german-like language
where you can't parse until the sentence is complete, here the solution
seems to be to parse a minimal extract:
cat > MesgFile (read line 0<&3 ; echo "Txt2Server" 1>&3) 3 <> $Server

But why/where does `cat > MesgFile` come in?

And by further simplifying, what about:
cat > MesgFile ls 3<>$Server
OR
cat > MesgFile ls
which is invalid.

PS.I'll be off-line for a few days

Chris Davies

unread,
Mar 30, 2013, 5:28:03 PM3/30/13
to
In comp.os.linux.misc Avoi...@gmail.com wrote:
> Which you would never write [nor echo "hello" | cat | cat | cat ]

As CFAJ mentioned, this would work. Follow the (simplified) set of rules
I gave you and you'll see that they apply: the "hello" is written the
first cat, which writes to the second, which writes to the third. That
final cat writes to the terminal because no other output target has
been specified.


> So then:
> cat>/tmp/mesgFile
> (
> read line 0<&3 ; echo "$line">$log
> case "$line" in 2*) ;; *) echo "QUIT" 1>&3 ; exit 0 ;; esac
> echo "HELO $local_name" 1>&3
> ) 3<>/dev/tcp/$smtp_server/25

> would mean
> "stdin [since none is provided]" writeTo /tmp/mesgFile
> the sequential output of the bracketed-statements
> [which also write to there OWN destinations]
> .... ??

No.

The shell applies redirection for stdout to /tmp/mesgFile. Cat is then
invoked, and it reads from stdin since no files are present on the command
line, and writes to its stdout. Remember that the shell has already
redirected stdout to a file, so cat effectively writes to the file. But
cat doesn't know this - all it knows is that it's writing to its stdout.

The bit in brackets is grouped as a single item. But before it's
executed the shell opens fd 3 and attaches its input/output to the
network socket tcp/25.

Now as you work through the lines inside the brackets you have this
additional descriptor available to you.


> Does: 3<>/dev/tcp/$smtp_server/25
> mean: let fd3 have input AND output to that-device?
>
> *THAT* is the 'fraud'(:-;) !!
> Only AFTER it's been used is it defined.

No. The shell applies redirection before the command (or subshell)
is executed. This is all documented in the man page.


> It would be good if the *nix docos put UP FRONT that
> 'it's not parsed sequentially left-to-right'; like computers
> work or mathematical theorems are proved.

It's in the shell man page under the heading REDIRECTION. This is
referenced several times from the section SHELL GRAMMAR that explains
the basic shell syntax.

Chris

Joe Beanfish

unread,
Apr 1, 2013, 11:32:49 AM4/1/13
to
On Fri, 29 Mar 2013 21:10:40 +0000, Avoid9Pdf wrote:
> In article <rovg2ax...@news.roaima.co.uk>, Chris Davies
> <chris-...@roaima.co.uk> wrote:
> But the original code used THIS syntax, and that may be the key to
> understanding the code. So then:
> cat>/tmp/mesgFile
> (
> read line 0<&3 ; echo "$line">$log case "$line" in 2*) ;; *) echo
> "QUIT" 1>&3 ; exit 0 ;; esac echo "HELO $local_name" 1>&3
> ) 3<>/dev/tcp/$smtp_server/25
>
> would mean "stdin [since none is provided]" writeTo /tmp/mesgFile the
> sequential output of the bracketed-statements [which also write to there
> OWN destinations]
> .... ??

I think part of your confusion is thinking the cat is somehow related
to the () section.

In the above cat will read stdin and write it to mesgFile. The script
will not proceed until that process is finished, ie when cat's stdin
reaches end of file. Then the script will proceed to execute the () block
with file-descriptor 3 directed to /dev/tcp/$smtp_server/25

Unknown

unread,
Apr 3, 2013, 4:00:35 AM4/3/13
to
On Mon, 01 Apr 2013 15:32:49 +0000, Joe Beanfish wrote:

> On Fri, 29 Mar 2013 21:10:40 +0000, Avoid9Pdf wrote:
>> In article <rovg2ax...@news.roaima.co.uk>, Chris Davies
>> <chris-...@roaima.co.uk> wrote:
>> But the original code used THIS syntax, and that may be the key to
>> understanding the code. So then:
>> cat>/tmp/mesgFile
>> (
>> read line 0<&3 ; echo "$line">$log case "$line" in 2*) ;; *) echo
>> "QUIT" 1>&3 ; exit 0 ;; esac echo "HELO $local_name" 1>&3
>> ) 3<>/dev/tcp/$smtp_server/25
>>
>> would mean "stdin [since none is provided]" writeTo /tmp/mesgFile the
>> sequential output of the bracketed-statements [which also write to
>> there OWN destinations]
>> .... ??
>
> I think part of your confusion is thinking the cat is somehow related to
> the () section.
>
Yes exactly: with this chaotic/unsequenced syntax, where the redirection
can appear anywhere, I assumed that `cat>/tmp/mesgFile` ALSO hangs on the
().

> In the above cat will read stdin and write it to mesgFile. The script
> will not proceed until that process is finished, ie when cat's stdin
> reaches end of file. Then the script will proceed to execute the ()
> block with file-descriptor 3 directed to /dev/tcp/$smtp_server/25

What *is* EOF for cat's stdIn? <EnterKey> ?
In the context of the overall task: a SMTP dialog; what is the use of
`cat>/tmp/mesgFile` ?

BTW, I've been telling myself and others how good *nix is, because it
uses the concatenative paradigm: where you can pipe transformations.
And if stage N tests OK, you don't need to worry/remember previous stages.
Now I find that, in this example, if the ()-block is 222-lines, you only
find at the END what FD3 is. So you've got to carry that info all that
way. That's crap !!
These FB/twitter kiddies, who've hi-jacked MY thread, need to realise
that computing progress is not limited by core-count, but by human
cognitive load. It's fundamental that terms/concepts are defined/
introduced before they are used.
==
Do you see the overall picture of how this code impliments a SMTP-client?
And how the: user, script, logFile, remoteServer; all communicate?

== TIA.


Unknown

unread,
Apr 3, 2013, 4:02:32 AM4/3/13
to
On Mon, 01 Apr 2013 15:32:49 +0000, Joe Beanfish wrote:

> On Fri, 29 Mar 2013 21:10:40 +0000, Avoid9Pdf wrote:
>> In article <rovg2ax...@news.roaima.co.uk>, Chris Davies
>> <chris-...@roaima.co.uk> wrote:
>> But the original code used THIS syntax, and that may be the key to
>> understanding the code. So then:
>> cat>/tmp/mesgFile
>> (
>> read line 0<&3 ; echo "$line">$log case "$line" in 2*) ;; *) echo
>> "QUIT" 1>&3 ; exit 0 ;; esac echo "HELO $local_name" 1>&3
>> ) 3<>/dev/tcp/$smtp_server/25
>>
>> would mean "stdin [since none is provided]" writeTo /tmp/mesgFile the
>> sequential output of the bracketed-statements [which also write to
>> there OWN destinations]
>> .... ??
>
> I think part of your confusion is thinking the cat is somehow related to
> the () section.
>
Yes exactly: with this chaotic/unsequenced syntax, where the redirection
can appear anywhere, I assumed that `cat>/tmp/mesgFile` ALSO hangs on the
().

> In the above cat will read stdin and write it to mesgFile. The script
> will not proceed until that process is finished, ie when cat's stdin
> reaches end of file. Then the script will proceed to execute the ()
> block with file-descriptor 3 directed to /dev/tcp/$smtp_server/25

Joe Beanfish

unread,
Apr 8, 2013, 10:47:33 AM4/8/13
to
On Wed, 03 Apr 2013 08:00:35 +0000, Unknown wrote:
> What *is* EOF for cat's stdIn? <EnterKey> ?

Nothing to do with "cat". If stdin is a file EOF is when all of the file
is read. If stdin is a pipe EOF is when the writer closes the pipe. If
stdin is a terminal EOF is typically ^D at the beginning of a line but
can be changed by stty. There are exceptions, like if non-blocking is
set, but those are the norms.


> BTW, I've been telling myself and others how good *nix is, because it
> uses the concatenative paradigm: where you can pipe transformations.
> And if stage N tests OK, you don't need to worry/remember previous
> stages.
> Now I find that, in this example, if the ()-block is 222-lines, you only
> find at the END what FD3 is. So you've got to carry that info all that
> way. That's crap !!

One can write well structured, modular, reusable code in just about any
language on just about any OS. One can also write complete shinola in
those same languages and systems. Don't blame the tools for how people
use them.
0 new messages