Recent

Author Topic: [SOLVED] Replace stdin with edit box text on a form?  (Read 4093 times)

Hopestation

  • Full Member
  • ***
  • Posts: 181
[SOLVED] Replace stdin with edit box text on a form?
« on: August 07, 2018, 06:26:31 pm »
Hi.
I want to run a command in Linux which requires "root" access.
The code below shows how to do it in a console.

program rootls;
 
{ Demonstrates using TProcess, redirecting stdout/stderr to our stdout/stderr,
calling sudo on Linux/OSX, and supplying input on stdin}
{$mode objfpc}{$H+}
 
uses
  Classes,
  Math, {for min}
  Process;
 
  procedure RunsLsRoot;
  var
    Proc: TProcess;
    CharBuffer: array [0..511] of char;
    ReadCount: integer;
    ExitCode: integer;
    SudoPassword: string;
  begin
    WriteLn('Please enter the sudo password:');
    Readln(SudoPassword);
    ExitCode := -1; //Start out with failure, let's see later if it works
    Proc := TProcess.Create(nil); //Create a new process
    try
      Proc.Options := [poUsePipes, poStderrToOutPut]; //Use pipes to redirect program stdin,stdout,stderr
      Proc.CommandLine := 'sudo -S ls /root'; //Run ls /root as root using sudo
      // -S causes sudo to read the password from stdin.
      Proc.Execute; //start it. sudo will now probably ask for a password

I want to do the same thing on a form with an Edit box for entering the password.
How do I get the text from the edit box into the command line in place of stdin?
« Last Edit: August 10, 2018, 03:22:37 pm by Hopestation »

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Replace stdin with edit box text on a form?
« Reply #1 on: August 08, 2018, 12:28:51 am »
hello,
you can try something like that (CommandLine is deprecated in recent versions of Lazarus) :
Code: Pascal  [Select][+][-]
  1. Proc.Executable := '/bin/bash'; // or /bin/sh
  2.    Proc.Parameters.Add('-c');
  3.    Proc.Parameters.Add('echo ' + Edit1.Caption  + ' | sudo -S ls /root');
  4.    Proc.Execute();
  5.  

Friendly J.P
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

Hopestation

  • Full Member
  • ***
  • Posts: 181
Re: Replace stdin with edit box text on a form?
« Reply #2 on: August 08, 2018, 01:02:24 pm »
Thanks JP.
I had already tried that without success.
My code is listed below, without all the comments:

unit getpartitioninfo;

{$mode objfpc}{$H+}

interface

uses
  Classes, Controls, Dialogs, FileUtil, Forms, Graphics, Process, StdCtrls,
  SysUtils;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
  private
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}
{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  hprocess: TProcess;
  sPass: String;
  OutputLines: TStringList;

begin
  sPass := Edit1.text;
  OutputLines:=TStringList.Create;
  hProcess := TProcess.Create(nil);
  hProcess.Executable := '/bin/sh';
  hprocess.Parameters.Add('-c');
  hprocess.Parameters.add('echo ' + sPass  + ' | sudo -S fdisk -l');
  hProcess.Options := hProcess.Options + [poWaitOnExit, poUsePipes];
  hProcess.Execute;

//  OutputLines.Add('stdout:');
  Memo1.Lines.add('stdout:');
//  OutputLines.LoadFromStream(hprocess.Output);
  Memo1.Lines.LoadFromStream(hprocess.Output);
//  OutputLines.Add('stderr:');
  Memo1.Lines.add('stderr:');
//  OutputLines.LoadFromStream(hProcess.Stderr);
  Memo1.Lines.LoadFromStream(hprocess.Stderr);
  Memo1.Lines.add(OutputLines.Text);
  Memo1.Lines.Add('Program completed');

  hProcess.Free;
  OutputLines.Free;
end;
End.

I enter my root password and click on the Run button and in the Memo I get:

[sudo] password for Hopestation:

Program completed

I presume that there isn't a stdout if this isn't a consol program, but there should be an output from hprocess.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Replace stdin with edit box text on a form?
« Reply #3 on: August 08, 2018, 01:07:22 pm »
hello,
try TprocessEx
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Replace stdin with edit box text on a form?
« Reply #4 on: August 08, 2018, 01:50:44 pm »
hello,
try TprocessEx

Works via same system so if TProcess doesn't return sudo'ed output, neither will tprocessex?

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Replace stdin with edit box text on a form?
« Reply #5 on: August 08, 2018, 05:47:00 pm »
when you use tprocessex with output in realtime (callback ProcessOutput) it works (see the attachment ).

The problem with Tprocessex is that the stderr is send to the same output that stdout.

it is for that that you can see in my attachment :
Quote
Mot de passe de jurassic :
sudo -S send the prompt on the stderr.
« Last Edit: August 08, 2018, 05:58:03 pm by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Replace stdin with edit box text on a form?
« Reply #6 on: August 08, 2018, 06:37:31 pm »
when you use tprocessex with output in realtime (callback ProcessOutput) it works (see the attachment ).

Afaik processex is nothing but a parametrisation of tprocess. IMHO it is better to point out what is the problem in the shown code (not implementing large output handling, and/or postderrtooutput in flags ) than to just have some blanket advise for a 3rd party unit.

Quote
The problem with Tprocessex is that the stderr is send to the same output that stdout.

Adding stderr output redirection is not really a problem for the example code shown.

Anyway, I'm currently reworking TProcess for the next major FPC iteration, so if you have suggestions, I'd be glad to hear them.


Code: Pascal  [Select][+][-]
  1. r39513 | marco | 2018-07-27 18:23:37 +0200 (Fri, 27 Jul 2018) | 3 lines
  2. Changed paths:
  3.    M /trunk/packages/fcl-process/src/process.pp
  4.  
  5.  * ReadInputStream factored out, analogous as suggested in mantis #32541.
  6.  
  7. Next step: make runcommand a method.
  8. ---
  9. r39514 | marco | 2018-07-27 20:16:50 +0200 (Fri, 27 Jul 2018) | 1 line
  10. Changed paths:
  11.    M /trunk/packages/fcl-process/src/process.pp
  12.  
  13.  * fix typo-gotcha probably introduced by an accidental save in the IDE after testing. Thanks to Karoly for reporting.
  14. ---
  15. r39516 | marco | 2018-07-28 15:59:21 +0200 (Sat, 28 Jul 2018) | 1 line
  16. Changed paths:
  17.    M /trunk/packages/fcl-process/src/process.pp
  18.  
  19.  * body of runcommand to TProcess class. If more flexibility is added to this function (onevent properties called in the loop), it becomes easier to run your own with slightly different features.
  20. ---
  21. r39517 | marco | 2018-07-28 17:42:25 +0200 (Sat, 28 Jul 2018) | 2 lines
  22. Changed paths:
  23.    M /trunk/packages/fcl-process/src/process.pp
  24.  
  25.  * Renamed intruncommand to RunCommandLoop.
  26.  * Added some events for basic parameterization.
  27. ---
  28. r39518 | marco | 2018-07-28 18:18:48 +0200 (Sat, 28 Jul 2018) | 1 line
  29. Changed paths:
  30.    M /trunk/packages/fcl-process/src/process.pp
  31.  
  32.  * reduce to one Event only, and use enum to signal what is happening.
  33. ---
  34. r39520 | marco | 2018-07-29 11:26:07 +0200 (Sun, 29 Jul 2018) | 2 lines
  35. Changed paths:
  36.    M /trunk/packages/fcl-process/src/process.pp
  37.  
  38.  * remove unused private field fterminalprogram
  39. ---
  40.  
  41. r39568 | marco | 2018-08-04 12:59:06 +0200 (Sat, 04 Aug 2018) | 1 line
  42. Changed paths:
  43.    M /trunk/packages/fcl-process/src/process.pp
  44.  
  45.  * alternate readinput with streams.

Hopestation

  • Full Member
  • ***
  • Posts: 181
Re: Replace stdin with edit box text on a form?
« Reply #7 on: August 09, 2018, 01:27:58 pm »
I've downloaded processutils.pas and added it to my project.

Here is my new code:

unit getpartitioninfo;

{$mode objfpc}{$H+}

interface

uses
  Classes, Controls, Dialogs, FileUtil, Forms, Graphics, Processutils, StdCtrls,  SysUtils;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  hprocess: TProcessEX;
  sPass: String;
  OutputLines: TStringList;

begin
  sPass := Edit1.text;
  OutputLines:=TStringList.Create;
  hProcess := TProcessEx.Create(nil);
  hProcess.Executable := '/bin/sh';
  hprocess.Parameters.Add('-c');
  hprocess.Parameters.add('echo ' + sPass  + ' | sudo -S fdisk -l');

  hProcess.Options := hProcess.Options + [poWaitOnExit, poUsePipes];
  hProcess.Execute;

  Memo1.Lines.add('stdout:');
  Memo1.Lines.LoadFromStream(hprocess.Output);
  Memo1.Lines.add('stderr:');
  Memo1.Lines.LoadFromStream(hprocess.Stderr);
  Memo1.Lines.add(OutputLines.Text);
  Memo1.Lines.Add('Program completed');

  hProcess.Free;
  OutputLines.Free;
 end;
End.

When I compile I get:
Compile Project, Target: Command_1: Exit code 256, Errors: 2
getpartitioninfo.pas(50,43) Error: Identifier not found "poWaitOnExit"
getpartitioninfo.pas(50,57) Error: Identifier not found "poUsePipes"

What do I have to do correct these?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Replace stdin with edit box text on a form?
« Reply #8 on: August 09, 2018, 01:42:09 pm »
Import unit process in the USES.

Hopestation

  • Full Member
  • ***
  • Posts: 181
Re: Replace stdin with edit box text on a form?
« Reply #9 on: August 09, 2018, 10:16:46 pm »
Thanks, I thought that ProcessEX replaced Process. I've now added it,

When I run the program it fails at the line

    Memo1.Lines.LoadFromStream(hprocess.Stderr);   

with message

Project Command_1 raised exception class 'External: SIGSEGV'.

 At address 49E2AC

Clicking OK gives

Classes$_$tstrings_$__$$_LOADFROMSTREAM$TSTREAM (231)
000000000049E292 486354241c               movslq 0x1c(%rsp),%rdx
000000000049E297 488d5201                 lea    0x1(%rdx),%rdx
000000000049E29B 488d7410ff               lea    -0x1(%rax,%rdx,1),%rsi
000000000049E2A0 8b542424                 mov    0x24(%rsp),%edx
000000000049E2A4 488b3c24                 mov    (%rsp),%rdi
000000000049E2A8 488b0424                 mov    (%rsp),%rax

000000000049E2AC 488b00                   mov    (%rax),%rax

Closing this and continuing I get

Debugger Exception Notification
Project Command_1 raised exception class 'RunError(216)

At address 49E2AC

If I keep continuing I finally get  stderr:  in the Memo but not Program Complete

If I comment out this line the program runs but the only Memo text is

  stderr:

  Program completed.

The lines

    Memo1.Lines.add('stdout:');
    Memo1.Lines.LoadFromStream(hprocess.Output);

 have not written anything to the Memo or they have been overwritten.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Replace stdin with edit box text on a form?
« Reply #10 on: August 09, 2018, 10:20:37 pm »
That's tprocessex specific then. Maybe JP knows.

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1228
Re: Replace stdin with edit box text on a form?
« Reply #11 on: August 10, 2018, 12:42:56 am »
hello,
you have a SigSegv with stderr because in TprocessEx execute you have that :
Code: Pascal  [Select][+][-]
  1.  Options := Options +[poUsePipes, poStderrToOutPut];
TprocessEx is only usefull if you want to display output from process in real time.
You can use Tprocess in your case. Your last code could work but you have some errors inside.
Try something like that :
Code: Pascal  [Select][+][-]
  1. procedure TForm1.BtGoSudo2Click(Sender: TObject);
  2. var OutputStrings : TStringList;
  3. var myProc : TProcess;
  4. begin
  5.    try
  6.    OutputStrings := TStringList.Create;
  7.    myProc := TProcess.Create(nil);
  8.    myProc.Executable := '/bin/bash'; // or /bin/sh
  9.    myProc.Parameters.Add('-c');
  10.    myProc.Parameters.Add('echo ' + Edit1.Caption  + ' | sudo -p "" -S ls -l /root');
  11.    myProc.Options := myProc.Options + [poWaitOnExit, poUsePipes];
  12.    myProc.Execute;
  13.    MemConsole.Lines.add('stdout:');
  14.    OutputStrings.LoadFromStream(myProc.Output);
  15.    MemConsole.Lines.AddStrings(OutputStrings);
  16.    MemConsole.Append('======================');
  17.    MemConsole.Lines.add('stderr:');
  18.    OutputStrings.LoadFromStream(myProc.Stderr);
  19.    MemConsole.Lines.AddStrings(OutputStrings);
  20.    MemConsole.Append('======================');
  21.    MemConsole.Lines.Add('Program completed');
  22.    finally
  23.      myProc.Free;
  24.      myProc := nil;
  25.      OutputStrings.Free;
  26.    end;
  27. end;

the -p ""  in the sudo command is there to not display prompt password.

Friendly, J.P
« Last Edit: August 10, 2018, 01:15:01 am by Jurassic Pork »
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

Hopestation

  • Full Member
  • ***
  • Posts: 181
Re: Replace stdin with edit box text on a form?
« Reply #12 on: August 10, 2018, 03:22:15 pm »
Thanks Marcov & JP.
I've replaced "ls" with "fdsk" and got a full listing.

 

TinyPortal © 2005-2018