OSProcess and multiline input

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

OSProcess and multiline input

Sean P. DeNigris
Administrator
I'm trying to pass a multiline argument, but none of the things that work in the shell seem to work with OSP.

I passed both of the following to PipeableOSProcess>>waitForCommand: with a "No such file or directory" error, which usually means that the multiline part was not processed correctly. However, if I copy/paste them into the shell, they work fine

heredoc:
'/usr/bin/osascript -ss  <<-EOF
tell application "Safari" to activate
tell application "Terminal" to activate
EOF'

double-quoted string:
'/usr/bin/osascript -ss  -e "
tell application \"Safari\" to activate
tell application \"Terminal\" to activate"'

Why are these not working?

Thanks.
Sean
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: OSProcess and multiline input

Eliot Miranda-2


On Fri, Feb 24, 2012 at 1:53 PM, Sean P. DeNigris <[hidden email]> wrote:
I'm trying to pass a multiline argument, but none of the things that work in
the shell seem to work with OSP.

I passed both of the following to PipeableOSProcess>>waitForCommand: with a
"No such file or directory" error, which usually means that the multiline
part was not processed correctly. However, if I copy/paste them into the
shell, they work fine

heredoc:
'/usr/bin/osascript -ss  <<-EOF
tell application "Safari" to activate
tell application "Terminal" to activate
EOF'

double-quoted string:
'/usr/bin/osascript -ss  -e "
tell application \"Safari\" to activate
tell application \"Terminal\" to activate"'

Why are these not working?

OSP is not a shell.  Ask yourself what a program receives when iyt is invoked with the two examples above.  Then provide the equivalent argument to OSP and you'll find it'll work.  OSP is an interface to exec.  A shell is an interface to exec.  OSP doesn't parse arguments, just passes them onto exec.  A shell does parse arguments before passing them onto exec.  So the shell input

"
tell application \"Safari\" to activate
tell application \"Terminal\" to activate"

is a string argument which in Smalltalk would be written

(String with: Character lf), 'tell application "Safari" to activate', (String with: Character lf), 'tell application "Terminal" to activate'
 

HTH


Thanks.
Sean

--
View this message in context: http://forum.world.st/OSProcess-and-multiline-input-tp4418726p4418726.html
Sent from the Squeak - Dev mailing list archive at Nabble.com.




--
best,
Eliot



Reply | Threaded
Open this post in threaded view
|

Re: OSProcess and multiline input

Sean P. DeNigris
Administrator
Eliot Miranda-2 wrote
OSP is an interface to exec.
That's good to know. Thanks.

I investigated further and accidentally found out that it wasn't the multi-line part at all that was the problem. It was that my string contained an ellipsis, which forced the argument to waitForCommand: into a WideString. Is there a workaround? can OSP only handle ByteStrings?

Thanks.
Sean
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: OSProcess and multiline input

David T. Lewis
In reply to this post by Eliot Miranda-2
On Fri, Feb 24, 2012 at 02:00:12PM -0800, Eliot Miranda wrote:

> On Fri, Feb 24, 2012 at 1:53 PM, Sean P. DeNigris <[hidden email]>wrote:
>
> > I'm trying to pass a multiline argument, but none of the things that work
> > in
> > the shell seem to work with OSP.
> >
> > I passed both of the following to PipeableOSProcess>>waitForCommand: with a
> > "No such file or directory" error, which usually means that the multiline
> > part was not processed correctly. However, if I copy/paste them into the
> > shell, they work fine
> >
> > heredoc:
> > '/usr/bin/osascript -ss  <<-EOF
> > tell application "Safari" to activate
> > tell application "Terminal" to activate
> > EOF'
> >
> > double-quoted string:
> > '/usr/bin/osascript -ss  -e "
> > tell application \"Safari\" to activate
> > tell application \"Terminal\" to activate"'
> >
> > Why are these not working?
> >
>
> OSP is not a shell.  Ask yourself what a program receives when iyt is
> invoked with the two examples above.  Then provide the equivalent argument
> to OSP and you'll find it'll work.  OSP is an interface to exec.  A shell
> is an interface to exec.  OSP doesn't parse arguments, just passes them
> onto exec.  A shell does parse arguments before passing them onto exec.  So
> the shell input
>
> "
> tell application \"Safari\" to activate
> tell application \"Terminal\" to activate"
>
> is a string argument which in Smalltalk would be written
>
> (String with: Character lf), 'tell application "Safari" to
> activate', (String with: Character lf), 'tell application "Terminal" to
> activate'
>

Exactly so. PipeableOSProcess class>>command: will take the string you
provide and pass it directly to a unix shell (/bin/sh which in most cases
is a link to bash). It will exec that /bin/sh program, providing your
input string directly to /bin/sh for processing. In turn, /bin/sh does
its normal processing, and executes whatever programs you asked it to
run. This means that the string you provide as input should contain exactly
the characters that you would have typed on a keyboard and sent through
the terminal driver to the /bin/sh program. Any <cr> or <lf> characters,
quote marks, and so forth in the the string are passed directly to the
/bin/sh program, which is the program that actually executes your command.

This may seem confusing if you are trying to send multiple lines of text
to the shell, because the "multiple lines" are really just a string with
some <cr> or <lf> characters embedded. You think of them as lines of text
because the unix terminal driver handling your keyboard processes them
that way; it waits until you hit your "enter" key before passing a line
of input to the shell. But from the point of view of the shell, it is just
a stream of bytes being sent to the shell, and by convention the shell
treats a bunch of characters ending with a <lf> as a line of input.

Of course it is possible to handle a lot of this input parsing in Smalltalk,
and that is what the classes in package CommandShell do. This allows you
to do the input parsing directly without the assistance of a unix /bin/sh
program. In other words, in your example we would separate the lines of
input text, parse each line to interpret the tokens and expand file names
as if we were a unix shell, and then directly invoke each individual program
in each command line without the assistance of a real unix shell. And because
each program that you run ends with an exit status code that it provides to
the shell, we can make use of that exit status in Smalltalk, and do some
conditional processing just as might be done by the real /bin/sh program.

Dave


Reply | Threaded
Open this post in threaded view
|

Re: OSProcess and multiline input

David T. Lewis
In reply to this post by Sean P. DeNigris
On Fri, Feb 24, 2012 at 03:46:58PM -0800, Sean P. DeNigris wrote:

>
> Eliot Miranda-2 wrote
> >
> > OSP is an interface to exec.
>
> That's good to know. Thanks.
>
> I investigated further and accidentally found out that it wasn't the
> multi-line part at all that was the problem. It was that my string contained
> an ellipsis, which forced the argument to waitForCommand: into a WideString.
> Is there a workaround? can OSP only handle ByteStrings?

OSProcess connects to external processes using a StandardFileStream rather
than a MultiByteFileStream, and I suspect that this is related to your
problem. Squeak's multi-byte character support did not yet exist when I
wrote OSProcess and CommandShell, and I am afraid that an update for this
is long overdue ...

In any case, if you can think of a way to convert your multi-byte input
string into exactly the steam of bytes that the program expects on its
input (more or less as Eliot was suggesting in his reply), then you may
find that it works. I don't have a Mac to try any of this on, so I really
should not attempt to guess at it, but I have a hunch that if you were
to convert your multi-byte input string into a byte array, thence back
to a string of 8-bit characters (two "characters" for each 16-bit character),
then feed this to a PipeableOSProcess, it might just work. Please let me
know in the unlikely event that I guessed right ;-)

Dave


Reply | Threaded
Open this post in threaded view
|

Re: OSProcess and multiline input

Sean P. DeNigris
Administrator
David T. Lewis wrote
I have a hunch that if you were
to convert your multi-byte input string into a byte array, thence back
to a string of 8-bit characters
I tried aWideString asByteArray asString (as well as some other experiments), which did not work. Is that what you meant?

Thanks.
Sean
Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: OSProcess and multiline input

Bert Freudenberg

On 28.02.2012, at 03:58, Sean P. DeNigris wrote:

>
> David T. Lewis wrote
>>
>> I have a hunch that if you were
>> to convert your multi-byte input string into a byte array, thence back
>> to a string of 8-bit characters
>
> I tried aWideString asByteArray asString (as well as some other
> experiments), which did not work. Is that what you meant?


Err, no. You need to encode it. Try squeakToUtf8. This converts from a WideString to a ByteString using UTF8 encoding.

- Bert -