Lazarus

Programming => General => Topic started by: rnfpc on July 14, 2019, 10:19:33 am

Title: Why this command not working with RunCommand?
Post by: rnfpc on July 14, 2019, 10:19:33 am
I am working on Debian Stable Linux system with fpc version 3.0.0. On my system, the command 'alias' produces following output:
Code: Pascal  [Select][+][-]
  1. alias ll='ls -ltrk'
  2. alias ls='ls --color=auto'
I also try to run it from following pascal file:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. uses Process;
  3. var s: ansistring;
  4. begin
  5.         if RunCommand('alias', [], s)
  6.         then writeln(s);
  7. end.
Though above file compiles and runs without any error, it produces no output.

Similarly, following also does not work:
Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','alias'],s)
  2. then writeln(s);

Following code, where I try to run an alias, also does not work:
Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','ll'],s)
  2. then writeln(s);

'll' is an alias on my system as shown above.

Following code from https://wiki.freepascal.org/Executing_External_Programs#.28Process..29RunCommand works all right:

Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','echo $PATH'],s)
  2. then writeln(s);

Following summarizes my problem:
Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','echo $PATH'],s) then writeln('res1:',s);
  2. if RunCommand('/bin/bash',['-c','alias'],s) then writeln('res2:',s);
  3. if RunCommand('/bin/bash',['-c','ll'],s) then writeln('res3:',s);
  4. if RunCommand('echo $PATH', [], s) then writeln('res4:',s);
  5. if RunCommand('alias', [], s) then writeln('res5:',s);
  6. if RunCommand('ll', [], s) then writeln('res6:',s);
produces following output:
Code: Pascal  [Select][+][-]
  1. res1:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
  2.  
  3. res2:
First line gives correct output, 2nd line gives blank output; all others give no output.

Where is the problem and how can I run 'alias' and 'll' commands from pascal files?
Title: Re: Why this command not working with RunCommand?
Post by: lucamar on July 14, 2019, 10:36:45 am
Try like this:
Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','alias'],s, [poUsePipes, poWaitOnExit])
  2. then writeln(s);

and the same for the rest.

ETA: All those lines that give no output? That's because they are not "programs" one executes but bash commands. You must pass them to the executable "bash" so that it can interpret and execute them.
Title: Re: Why this command not working with RunCommand?
Post by: rnfpc on July 14, 2019, 12:34:16 pm
Try like this:
Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','alias'],s, [poUsePipes, poWaitOnExit])
  2. then writeln(s);
and the same for the rest.

This does not work. The error is:
Code: Pascal  [Select][+][-]
  1. Error: Wrong number of parameters specified for call to "RunCommand"
Title: Re: Why this command not working with RunCommand?
Post by: marcov on July 14, 2019, 12:36:05 pm

I had hoped that defining the aliases in .bashrc would help (so that bash would interpret .bashrc it on aux shell execution), but it doesn't. Anyway, this requires some research in how to force bash to interpret some file with aliases on secundary/auxilary execution.

IOW it is a bash, not a runcommand problem.

To get you started, a quick search yielded : https://unix.stackexchange.com/questions/1496/why-doesnt-my-bash-script-recognize-aliases
Title: Re: Why this command not working with RunCommand?
Post by: rnfpc on July 14, 2019, 12:38:49 pm
ETA: All those lines that give no output? That's because they are not "programs" one executes but bash commands. You must pass them to the executable "bash" so that it can interpret and execute them.

Following using bash also does not work:
Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','alias'],s) then writeln('res2:',s);
  2. if RunCommand('/bin/bash',['-c','ll'],s) then writeln('res3:',s);
Title: Re: Why this command not working with RunCommand?
Post by: lucamar on July 14, 2019, 08:03:07 pm
Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','alias'],s, [poUsePipes, poWaitOnExit])
  2. then writeln(s);

This does not work. The error is:
Error: Wrong number of parameters specified for call to "RunCommand"

Sorry for the delay, been out most of the day. It should not give you that error; it's a perfectly valid invocation of RunCommand(). I've just tested with this code:
Code: Pascal  [Select][+][-]
  1. resourcestring
  2.   sNotFound = 'Can''t find "%s"';
  3.   sCmdToRun = '%s %s';
  4.   sCmdError = 'Error: RunCommand() failed';
  5.   sResult   = 'Result:' + LineEnding +
  6.               '%s' + LineEnding;
  7.   sNoResult = 'Result: Nothing to display.';
  8.  
  9. procedure TMainForm.btDoTestClick(Sender: TObject);
  10. var
  11.   cmd: String = '';
  12.   cmdRes: String = '';
  13. begin
  14.   cmd := FindDefaultExecutablePath('bash');
  15.   if cmd = '' then
  16.     ShowMessageFmt(sNotFound, ['bash'])
  17.   else begin
  18.     Memo.Text := Format(sCmdToRun, [cmd, '-c alias']);
  19.     if not RunCommand(cmd, ['-c', 'alias'], cmdRes, [poStderrToOutPut]) then
  20.       Memo.Lines.Add(sCmdError);
  21.     if cmdRes.IsEmpty then
  22.       Memo.Lines.Add(sNoResult)
  23.     else
  24.       Memo.Lines.Add(sResult, [cmdRes]);
  25.   end;
  26. end;

and it compiles and runs without fault. See attached image.

As you can see invoking 'bash -c alias' in this machine also produces nothing so Marco seems to be right: aliases are not inherited by the child process. Bad luck!

To be clear: It's not that the command doesn't work, it's that there are no aliases so it outputs nothing.
Title: Re: Why this command not working with RunCommand?
Post by: del on December 06, 2019, 01:48:27 am
I get around a lot of these problems by just calling a shell script using TProcess. Which is fine for hobby stuff, but for commercial stuff it would involve including the scripts (.sh for Linux, .ps1 for Windows) in the distribution. Is this ever done? Does anybody know of this ever being done in a "commercial" context?
Title: Re: Why this command not working with RunCommand?
Post by: winni on December 06, 2019, 02:33:13 am
Hi!

Linux alias is bound to a  specific user. If user A set his aliases in the ~/.bashrc or  ~/.bash_aliases then they are not valid for user B.

With runcommand you start a new instance of the bash with user "unknown" or user "lazarus" - I don't know. But this bash does not know anything about your aliases.

But you could read the bashrc of the needed user and look what aliases there are stored.
But a lot of work - just for an alias.

So if you start a bash with lazarus - it is not your bash!

Winni
Title: Re: Why this command not working with RunCommand?
Post by: winni on December 06, 2019, 03:56:23 am
Hi!

The test to figure  out the name of the user of the bash, started by lazarus.

With the linux command who you can get a lot of infos: who is logged in, start time, hostname etc

This shows the boot time:

Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','/usr/bin/who -b'],s) then showMessage(s);

There is an undocumented feature for who to figure out as whom you are logged in:

Code: Bash  [Select][+][-]
  1. who am I

But this is a feature with the ability for a lot of jokes. who with two parameters returns always the user name. So you can enter who MyGirl loves....

Anyway, if you use it with the bash started by lazarus

Code: Pascal  [Select][+][-]
  1. if RunCommand('/bin/bash',['-c','/usr/bin/who am I'],s) then showMessage(s);

The resulting string is empty.

So the user name is ''. And not rnfpc or lucamar.

Winni
Title: Re: Why this command not working with RunCommand?
Post by: MarkMLl on December 06, 2019, 09:06:00 am
Sorry for another very late response. I was playing with some related stuff the other day and found that  bash -c  is very picky when it is parsing multiple parameters. The way to explore this appears to be by issuing a command like

Code: [Select]
$ bash -c ls -l

where you might find that the -l option isn't correctly passed to ls, and then comparing it with

Code: [Select]
$ bash -c 'ls -l'

which is what appears to work. Doing that allowed me to sort out a TProcess problem (I was attempting to start Lazarus with --pcp so that I could debug a child program).

That explains the failed command that @lucamar reported, and the successful run of  who  by @winni.

Code: [Select]
$ who
markMLl  tty7         2019-11-26 08:04 (:0)
markMLl  pts/0        2019-11-26 08:04 (:0)

$ who am i
markMLl  pts/7        2019-12-06 07:54 (:0)

$ bash -c who am i
markMLl  tty7         2019-11-26 08:04 (:0)
markMLl  pts/0        2019-11-26 08:04 (:0)

$ bash -c 'who am i'
markMLl  pts/7        2019-12-06 07:54 (:0)

MarkMLl



Title: Re: Why this command not working with RunCommand?
Post by: marcov on December 06, 2019, 09:33:35 am
yes, shell commandlines should be passed as one parameter.
TinyPortal © 2005-2018