View Issue Details

IDProjectCategoryView StatusLast Update
0038608LazarusIDEpublic2021-03-16 16:56
ReporterMark Morgan Lloyd Assigned ToMattias Gaertner  
PrioritynormalSeverityfeatureReproducibilityalways
Status assignedResolutionopen 
Product Version2.1 (SVN) 
Summary0038608: Run as different user
DescriptionAttached patch adds "run as" UI elements to the "Compiler commands ... Execute after" section of the project options.

Rationale described at https://forum.lazarus.freepascal.org/index.php/topic,53541.0.html In brief, it's to allow POSIX capabilities or other installation steps to be executed as root/administrator.
Additional InformationVisually OK on Linux (KDE desktop) using the GTK2 widget set at the default 96dpi.

Expect some other system component (e.g. sudo on unix) to request authentication (a password etc.) and check authorisation .

I've left it disabled pending writing backend code, and haven't attempted to integrate it with i18n.
TagsNo tags attached.
Fixed in Revision
LazTarget-
WidgetsetGTK 2
Attached Files

Activities

Mark Morgan Lloyd

2021-03-09 17:10

reporter  

runas.diff (15,758 bytes)   
Index: ide/frames/compiler_compilation_options.pas
===================================================================
--- ide/frames/compiler_compilation_options.pas	(revision 64770)
+++ ide/frames/compiler_compilation_options.pas	(working copy)
@@ -26,8 +26,11 @@
 
   TCompilerCompilationOptionsFrame = class(TAbstractIDEOptionsEditor)
     BrowseCompilerButton: TButton;
+    chkExecAfterRunAsUser: TCheckBox;
     ExecAfterParsersCheckListBox: TCheckListBox;
     ExecAfterParsersLabel: TLabel;
+    ExecAfterRunAsUserButton: TButton;
+    ExecAfterRunAsUserLabel: TLabel;
     ExecBeforeBrowseButton: TButton;
     chkCompilerBuild: TCheckBox;
     chkCompilerCompile: TCheckBox;
@@ -43,6 +46,7 @@
     ExecAfterBrowseButton: TButton;
     ExecBeforeParsersCheckListBox: TCheckListBox;
     ExecuteAfterCommandComboBox: TComboBox;
+    ExecuteAfterRunAsUserComboBox: TComboBox;
     ExecuteAfterCommandLabel: TLabel;
     ExecuteAfterGroupBox: TGroupBox;
     ExecuteBeforeCommandComboBox: TComboBox;
@@ -55,6 +59,7 @@
     lblRunIfExecAfter: TLabel;
     lblRunIfExecBefore: TLabel;
     procedure CompCmdBrowseButtonClick(Sender: TObject);
+    procedure ExecAfterRunAsUserButtonClick(Sender: TObject);
   private
     procedure ReadSettingsParsers(ToolOpts: TCompilationToolOptions;
       Cmb: TCheckListBox);
@@ -174,6 +179,12 @@
   end;
 end;
 
+procedure TCompilerCompilationOptionsFrame.ExecAfterRunAsUserButtonClick(
+  Sender: TObject);
+begin
+
+end;
+
 procedure TCompilerCompilationOptionsFrame.ReadSettingsParsers(
   ToolOpts: TCompilationToolOptions; Cmb: TCheckListBox);
 var
Index: ide/frames/compiler_compilation_options.lfm
===================================================================
--- ide/frames/compiler_compilation_options.lfm	(revision 64770)
+++ ide/frames/compiler_compilation_options.lfm	(working copy)
@@ -12,9 +12,9 @@
     AnchorSideLeft.Control = Owner
     AnchorSideTop.Control = Owner
     Left = 0
-    Height = 19
+    Height = 21
     Top = 0
-    Width = 118
+    Width = 140
     Caption = 'chkCreateMakefile'
     ParentShowHint = False
     ShowHint = True
@@ -27,23 +27,23 @@
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
     Left = 0
-    Height = 166
-    Top = 283
+    Height = 192
+    Top = 321
     Width = 741
     Anchors = [akTop, akLeft, akRight]
     AutoSize = True
     BorderSpacing.Top = 6
     Caption = 'ExecuteAfterGroupBox'
-    ClientHeight = 146
-    ClientWidth = 737
+    ClientHeight = 172
+    ClientWidth = 739
     TabOrder = 3
     object lblRunIfExecAfter: TLabel
       AnchorSideLeft.Control = ExecuteAfterGroupBox
       AnchorSideTop.Control = ExecuteAfterGroupBox
       Left = 6
-      Height = 15
+      Height = 19
       Top = 6
-      Width = 90
+      Width = 109
       BorderSpacing.Around = 6
       Caption = 'lblRunIfExecAfter'
       ParentColor = False
@@ -53,9 +53,9 @@
       AnchorSideTop.Control = ExecuteAfterCommandComboBox
       AnchorSideTop.Side = asrCenter
       Left = 6
-      Height = 15
-      Top = 35
-      Width = 151
+      Height = 19
+      Top = 39
+      Width = 178
       BorderSpacing.Around = 6
       Caption = 'ExecuteAfterCommandLabel'
       ParentColor = False
@@ -64,10 +64,10 @@
       AnchorSideLeft.Control = lblRunIfExecAfter
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteAfterGroupBox
-      Left = 126
-      Height = 19
+      Left = 145
+      Height = 21
       Top = 6
-      Width = 133
+      Width = 156
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecAfterCompile'
@@ -77,10 +77,10 @@
       AnchorSideLeft.Control = chkExecAfterCompile
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteAfterGroupBox
-      Left = 289
-      Height = 19
+      Left = 331
+      Height = 21
       Top = 6
-      Width = 115
+      Width = 137
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecAfterBuild'
@@ -90,10 +90,10 @@
       AnchorSideLeft.Control = chkExecAfterBuild
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteAfterGroupBox
-      Left = 434
-      Height = 19
+      Left = 498
+      Height = 21
       Top = 6
-      Width = 109
+      Width = 130
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecAfterRun'
@@ -105,15 +105,15 @@
       AnchorSideTop.Control = chkExecAfterCompile
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = ExecAfterBrowseButton
-      Left = 169
-      Height = 23
-      Top = 31
-      Width = 539
+      Left = 196
+      Height = 31
+      Top = 33
+      Width = 514
       Anchors = [akTop, akLeft, akRight]
       BorderSpacing.Left = 12
       BorderSpacing.Top = 6
       BorderSpacing.Bottom = 6
-      ItemHeight = 15
+      ItemHeight = 0
       TabOrder = 3
       Text = 'ExecuteAfterCommandComboBox'
     end
@@ -123,14 +123,13 @@
       AnchorSideRight.Side = asrBottom
       AnchorSideBottom.Control = ExecuteAfterCommandComboBox
       AnchorSideBottom.Side = asrBottom
-      Left = 708
-      Height = 23
-      Top = 31
+      Left = 710
+      Height = 31
+      Top = 33
       Width = 23
       Anchors = [akTop, akRight, akBottom]
       BorderSpacing.Right = 6
       Caption = '…'
-      OnClick = CompCmdBrowseButtonClick
       TabOrder = 4
     end
     object ExecAfterParsersLabel: TLabel
@@ -137,12 +136,12 @@
       AnchorSideLeft.Control = ExecuteAfterGroupBox
       AnchorSideTop.Control = ExecAfterParsersCheckListBox
       Left = 6
-      Height = 15
-      Top = 63
-      Width = 114
+      Height = 19
+      Top = 73
+      Width = 135
       BorderSpacing.Left = 6
       BorderSpacing.Top = 3
-      Caption = 'ExecAfterParsersLabel'
+      Caption = 'ExecAfterParserLabel'
       ParentColor = False
     end
     object ExecAfterParsersCheckListBox: TCheckListBox
@@ -150,14 +149,78 @@
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteAfterCommandComboBox
       AnchorSideTop.Side = asrBottom
-      Left = 126
-      Height = 80
-      Top = 60
+      Left = 147
+      Height = 96
+      Top = 70
       Width = 180
       BorderSpacing.Around = 6
       ItemHeight = 0
       TabOrder = 5
+      TopIndex = -1
     end
+    object chkExecAfterRunAsUser: TCheckBox
+      AnchorSideLeft.Control = ExecAfterParsersCheckListBox
+      AnchorSideLeft.Side = asrBottom
+      AnchorSideTop.Control = ExecAfterParsersLabel
+      Left = 345
+      Height = 21
+      Top = 79
+      Width = 163
+      BorderSpacing.Left = 12
+      BorderSpacing.Around = 6
+      Caption = 'Run as a different user'
+      Enabled = False
+      TabOrder = 6
+    end
+    object ExecuteAfterRunAsUserComboBox: TComboBox
+      AnchorSideLeft.Control = ExecAfterRunAsUserLabel
+      AnchorSideLeft.Side = asrBottom
+      AnchorSideTop.Control = ExecAfterRunAsUserLabel
+      AnchorSideTop.Side = asrCenter
+      AnchorSideRight.Control = ExecuteAfterCommandComboBox
+      AnchorSideRight.Side = asrBottom
+      Left = 419
+      Height = 31
+      Top = 100
+      Width = 291
+      Anchors = [akTop, akLeft, akRight]
+      BorderSpacing.Left = 6
+      BorderSpacing.Top = 6
+      BorderSpacing.Bottom = 6
+      Enabled = False
+      ItemHeight = 0
+      TabOrder = 7
+    end
+    object ExecAfterRunAsUserLabel: TLabel
+      AnchorSideLeft.Control = chkExecAfterRunAsUser
+      AnchorSideTop.Control = chkExecAfterRunAsUser
+      AnchorSideTop.Side = asrBottom
+      Left = 345
+      Height = 19
+      Top = 106
+      Width = 68
+      BorderSpacing.Top = 6
+      Caption = 'User name'
+      Enabled = False
+      ParentColor = False
+    end
+    object ExecAfterRunAsUserButton: TButton
+      AnchorSideTop.Control = ExecuteAfterRunAsUserComboBox
+      AnchorSideRight.Control = ExecuteAfterGroupBox
+      AnchorSideRight.Side = asrBottom
+      AnchorSideBottom.Control = ExecuteAfterRunAsUserComboBox
+      AnchorSideBottom.Side = asrBottom
+      Left = 710
+      Height = 31
+      Top = 100
+      Width = 23
+      Anchors = [akTop, akRight, akBottom]
+      BorderSpacing.Right = 6
+      Caption = '…'
+      Enabled = False
+      OnClick = ExecAfterRunAsUserButtonClick
+      TabOrder = 8
+    end
   end
   object grpCompiler: TGroupBox
     AnchorSideLeft.Control = Owner
@@ -166,23 +229,23 @@
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
     Left = 0
-    Height = 80
-    Top = 197
+    Height = 90
+    Top = 225
     Width = 741
     Anchors = [akTop, akLeft, akRight]
     AutoSize = True
     BorderSpacing.Top = 6
     Caption = 'grpCompiler'
-    ClientHeight = 60
-    ClientWidth = 737
+    ClientHeight = 70
+    ClientWidth = 739
     TabOrder = 2
     object lblRunIfCompiler: TLabel
       AnchorSideLeft.Control = grpCompiler
       AnchorSideTop.Control = grpCompiler
       Left = 6
-      Height = 15
+      Height = 19
       Top = 6
-      Width = 90
+      Width = 104
       BorderSpacing.Around = 6
       Caption = 'lblRunIfCompiler'
       ParentColor = False
@@ -192,9 +255,9 @@
       AnchorSideTop.Control = cobCompiler
       AnchorSideTop.Side = asrCenter
       Left = 6
-      Height = 15
-      Top = 35
-      Width = 62
+      Height = 19
+      Top = 39
+      Width = 70
       BorderSpacing.Around = 6
       Caption = 'lblCompiler'
       ParentColor = False
@@ -203,12 +266,12 @@
       AnchorSideLeft.Control = lblRunIfCompiler
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = grpCompiler
-      Left = 126
-      Height = 19
+      Left = 146
+      Height = 21
       Top = 6
-      Width = 133
+      Width = 151
       BorderSpacing.Left = 30
-      BorderSpacing.Top = 6
+      BorderSpacing.Around = 6
       Caption = 'chkCompilerCompile'
       TabOrder = 0
     end
@@ -216,10 +279,10 @@
       AnchorSideLeft.Control = chkCompilerCompile
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = grpCompiler
-      Left = 289
-      Height = 19
+      Left = 327
+      Height = 21
       Top = 6
-      Width = 115
+      Width = 132
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkCompilerBuild'
@@ -229,10 +292,10 @@
       AnchorSideLeft.Control = chkCompilerBuild
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = grpCompiler
-      Left = 434
-      Height = 19
+      Left = 489
+      Height = 21
       Top = 6
-      Width = 109
+      Width = 125
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkCompilerRun'
@@ -244,15 +307,15 @@
       AnchorSideTop.Control = chkCompilerCompile
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = BrowseCompilerButton
-      Left = 80
-      Height = 23
-      Top = 31
-      Width = 628
+      Left = 88
+      Height = 31
+      Top = 33
+      Width = 622
       Anchors = [akTop, akLeft, akRight]
       BorderSpacing.Left = 12
       BorderSpacing.Top = 6
       BorderSpacing.Bottom = 6
-      ItemHeight = 15
+      ItemHeight = 0
       TabOrder = 3
       Text = 'cobCompiler'
     end
@@ -262,14 +325,13 @@
       AnchorSideRight.Side = asrBottom
       AnchorSideBottom.Control = cobCompiler
       AnchorSideBottom.Side = asrBottom
-      Left = 708
-      Height = 23
-      Top = 31
+      Left = 710
+      Height = 31
+      Top = 33
       Width = 23
       Anchors = [akTop, akRight, akBottom]
       BorderSpacing.Right = 6
       Caption = '…'
-      OnClick = CompCmdBrowseButtonClick
       ParentShowHint = False
       ShowHint = True
       TabOrder = 4
@@ -282,23 +344,23 @@
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
     Left = 0
-    Height = 166
-    Top = 25
+    Height = 192
+    Top = 27
     Width = 741
     Anchors = [akTop, akLeft, akRight]
     AutoSize = True
     BorderSpacing.Top = 6
     Caption = 'ExecuteBeforeGroupBox'
-    ClientHeight = 146
-    ClientWidth = 737
+    ClientHeight = 172
+    ClientWidth = 739
     TabOrder = 1
     object lblRunIfExecBefore: TLabel
       AnchorSideLeft.Control = ExecuteBeforeGroupBox
       AnchorSideTop.Control = ExecuteBeforeGroupBox
       Left = 6
-      Height = 15
+      Height = 19
       Top = 6
-      Width = 98
+      Width = 120
       BorderSpacing.Around = 6
       Caption = 'lblRunIfExecBefore'
       ParentColor = False
@@ -308,9 +370,9 @@
       AnchorSideTop.Control = ExecuteBeforeCommandComboBox
       AnchorSideTop.Side = asrCenter
       Left = 6
-      Height = 15
-      Top = 35
-      Width = 159
+      Height = 19
+      Top = 39
+      Width = 189
       BorderSpacing.Around = 6
       Caption = 'ExecuteBeforeCommandLabel'
       ParentColor = False
@@ -319,10 +381,10 @@
       AnchorSideLeft.Control = lblRunIfExecBefore
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteBeforeGroupBox
-      Left = 134
-      Height = 19
+      Left = 156
+      Height = 21
       Top = 6
-      Width = 141
+      Width = 167
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecBeforeCompile'
@@ -332,10 +394,10 @@
       AnchorSideLeft.Control = chkExecBeforeCompile
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteBeforeGroupBox
-      Left = 305
-      Height = 19
+      Left = 353
+      Height = 21
       Top = 6
-      Width = 123
+      Width = 148
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecBeforeBuild'
@@ -345,10 +407,10 @@
       AnchorSideLeft.Control = chkExecBeforeBuild
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteBeforeGroupBox
-      Left = 458
-      Height = 19
+      Left = 531
+      Height = 21
       Top = 6
-      Width = 117
+      Width = 141
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecBeforeRun'
@@ -360,15 +422,15 @@
       AnchorSideTop.Control = chkExecBeforeCompile
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = ExecBeforeBrowseButton
-      Left = 177
-      Height = 23
-      Top = 31
-      Width = 531
+      Left = 207
+      Height = 31
+      Top = 33
+      Width = 503
       Anchors = [akTop, akLeft, akRight]
       BorderSpacing.Left = 12
       BorderSpacing.Top = 6
       BorderSpacing.Bottom = 6
-      ItemHeight = 15
+      ItemHeight = 0
       TabOrder = 3
       Text = 'ExecuteBeforeCommandComboBox'
     end
@@ -379,22 +441,21 @@
       AnchorSideRight.Side = asrBottom
       AnchorSideBottom.Control = ExecuteBeforeCommandComboBox
       AnchorSideBottom.Side = asrBottom
-      Left = 708
-      Height = 23
-      Top = 31
+      Left = 710
+      Height = 31
+      Top = 33
       Width = 23
       Anchors = [akTop, akRight, akBottom]
       BorderSpacing.Right = 6
       Caption = '…'
-      OnClick = CompCmdBrowseButtonClick
       TabOrder = 4
     end
     object ExecBeforeParsersLabel: TLabel
       AnchorSideTop.Control = ExecBeforeParsersCheckListBox
       Left = 6
-      Height = 15
-      Top = 63
-      Width = 122
+      Height = 19
+      Top = 73
+      Width = 152
       BorderSpacing.Left = 6
       BorderSpacing.Top = 3
       Caption = 'ExecBeforeParsersLabel'
@@ -405,13 +466,14 @@
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteBeforeCommandComboBox
       AnchorSideTop.Side = asrBottom
-      Left = 134
-      Height = 80
-      Top = 60
+      Left = 164
+      Height = 96
+      Top = 70
       Width = 180
       BorderSpacing.Around = 6
       ItemHeight = 0
       TabOrder = 5
+      TopIndex = -1
     end
   end
 end
runas.diff (15,758 bytes)   

Mattias Gaertner

2021-03-11 12:17

manager   ~0129568

The patch only contains visual components, no implementation. Is this the correct patch?

Mark Morgan Lloyd

2021-03-13 09:28

reporter   ~0129623

For the moment yes, since it allows the editable fields to be activated under code control without risking damaging anything visual.

I'm confident that the supporting code can be implemented easily on Linux using sudo's capability to prompt for a password, however it will need to check for the existence of /etc/sudo.conf (the content is inaccessible to unprivileged users). If this file has not been created then it is unlikely that the system admin has put the line into it that tells sudo how to get the password.

I'm fairly confident that SunOS/Solaris will behave the same way, but I need to investigate getting a system up and running.

I can't speak first-hand for Windows although I am told that there's an API. I don't know about Macs, which again is a good reason for starting off with disabled controls.

https://forum.lazarus.freepascal.org/index.php/topic,53541.msg396133.html#msg396133 explains the rationale, I don't think the facility would be needed for other build stages and debugging as a different user is obviously a completely different issue.

Mattias Gaertner

2021-03-13 11:58

manager   ~0129626

GUI without function creates too much confusion. When will you upload the implementation?

Mark Morgan Lloyd

2021-03-13 18:33

reporter   ~0129635

Last edited: 2021-03-13 18:40

View 2 revisions

I'll try to rough something out for Linux tomorrow (Sunday) or the day after, but at the moment I'm trying to re-cap the monitor on my desk.

Mark Morgan Lloyd

2021-03-16 16:56

reporter   ~0129714

Revised patch attached for unix, the components are made invisible for other OSes. I'm confident in the content of the attached .pas file, bit the diff needs attention from somebody with authority over the IDE since (a) I know that the Prefix() function is hung in the wrong place (b) the state of the checkbox and combobox aren't being saved so the next build doesn't see them and (c) the state doesn't persist between sessions.
runexecuteafterasuser.pas (3,148 bytes)   
unit RunExecuteAfterAsUser;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils;

(* Return true if the platform supports Sudo or a comparable mechanism.
*)
function HasDifferentUser(): boolean; platform; experimental;

(* Return true if the system has the prerequisites required to run a command as
  a different user. In most cases the user can be expected to have additional
  privilege so that he can bless the final binary with additional capabilities
  or sign it as having originated from a known organisation.
*)
function HasPrequisites(): boolean; platform; experimental;

(* The user has requested that the command passed as the parameter be run as a
  different (usually more-privileged) user. Construct an appropriate prefix.
*)
function Prefix(const command, asUser: string): string; platform; experimental;


implementation

{$ifndef UNIX }

(* Return true if the platform supports Sudo or a comparable mechanism.
*)
function HasDifferentUser(): boolean; platform; experimental;

begin
  result := false
end { HasDifferentUser } ;


(* Return true if the system has the prerequisites required to run a command as
  a different user. In most cases the user can be expected to have additional
  privilege so that he can bless the final binary with additional capabilities
  or sign it as having originated from a known organisation.
*)
function HasPrequisites(): boolean; platform; experimental;

begin
  result := false
end { HasPrequisites } ;

{$else UNIX }

(* Return true if the platform supports Sudo or a comparable mechanism.
*)
function HasDifferentUser(): boolean; platform; experimental;

begin
  result := true
end { HasDifferentUser } ;


(* Return true if the system has the prerequisites required to run a command as
  a different user. In most cases the user can be expected to have additional
  privilege so that he can bless the final binary with additional capabilities
  or sign it as having originated from a known organisation.
*)
function HasPrequisites(): boolean; platform; experimental;

begin

(* If it exists this file will probably not be readable by an unprivileged user,
  but it should contain something like

#
# Sudo askpass:
#
# An askpass helper program may be specified to provide a graphical
# password prompt for "sudo -A" support.  Sudo does not ship with its
# own askpass program but can use the OpenSSH askpass.
#
# Use the OpenSSH askpass
Path askpass /usr/bin/ssh-askpass
#
# Use the Gnome OpenSSH askpass
#Path askpass /usr/libexec/openssh/gnome-ssh-askpass

  as a minimum prerequisite to sudo being able to prompt for a password.
*)

  result := FileExists('/etc/sudo.conf')
end { HasPrequisites } ;


(* The user has requested that the command passed as the parameter be run as a
  different (usually more-privileged) user. Construct an appropriate prefix.
*)
function Prefix(const command, asUser: string): string; platform; experimental;

begin
  if (asUser = '') or (asUser = 'root') then
    result := 'sudo --askpass --reset-timestamp ' + command
  else
    result := 'sudo --askpass --reset-timestamp --user=' + asUser + ' ' + command
end { Prefix } ;

{$endif UNIX }

end.

runexecuteafterasuser.pas (3,148 bytes)   
runas2.diff (17,547 bytes)   
Index: ide/frames/compiler_compilation_options.lfm
===================================================================
--- ide/frames/compiler_compilation_options.lfm	(revision 64770)
+++ ide/frames/compiler_compilation_options.lfm	(working copy)
@@ -12,9 +12,9 @@
     AnchorSideLeft.Control = Owner
     AnchorSideTop.Control = Owner
     Left = 0
-    Height = 19
+    Height = 21
     Top = 0
-    Width = 118
+    Width = 140
     Caption = 'chkCreateMakefile'
     ParentShowHint = False
     ShowHint = True
@@ -27,23 +27,23 @@
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
     Left = 0
-    Height = 166
-    Top = 283
+    Height = 192
+    Top = 321
     Width = 741
     Anchors = [akTop, akLeft, akRight]
     AutoSize = True
     BorderSpacing.Top = 6
     Caption = 'ExecuteAfterGroupBox'
-    ClientHeight = 146
-    ClientWidth = 737
+    ClientHeight = 172
+    ClientWidth = 739
     TabOrder = 3
     object lblRunIfExecAfter: TLabel
       AnchorSideLeft.Control = ExecuteAfterGroupBox
       AnchorSideTop.Control = ExecuteAfterGroupBox
       Left = 6
-      Height = 15
+      Height = 19
       Top = 6
-      Width = 90
+      Width = 109
       BorderSpacing.Around = 6
       Caption = 'lblRunIfExecAfter'
       ParentColor = False
@@ -53,9 +53,9 @@
       AnchorSideTop.Control = ExecuteAfterCommandComboBox
       AnchorSideTop.Side = asrCenter
       Left = 6
-      Height = 15
-      Top = 35
-      Width = 151
+      Height = 19
+      Top = 39
+      Width = 178
       BorderSpacing.Around = 6
       Caption = 'ExecuteAfterCommandLabel'
       ParentColor = False
@@ -64,10 +64,10 @@
       AnchorSideLeft.Control = lblRunIfExecAfter
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteAfterGroupBox
-      Left = 126
-      Height = 19
+      Left = 145
+      Height = 21
       Top = 6
-      Width = 133
+      Width = 156
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecAfterCompile'
@@ -77,10 +77,10 @@
       AnchorSideLeft.Control = chkExecAfterCompile
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteAfterGroupBox
-      Left = 289
-      Height = 19
+      Left = 331
+      Height = 21
       Top = 6
-      Width = 115
+      Width = 137
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecAfterBuild'
@@ -90,10 +90,10 @@
       AnchorSideLeft.Control = chkExecAfterBuild
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteAfterGroupBox
-      Left = 434
-      Height = 19
+      Left = 498
+      Height = 21
       Top = 6
-      Width = 109
+      Width = 130
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecAfterRun'
@@ -105,15 +105,15 @@
       AnchorSideTop.Control = chkExecAfterCompile
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = ExecAfterBrowseButton
-      Left = 169
-      Height = 23
-      Top = 31
-      Width = 539
+      Left = 196
+      Height = 31
+      Top = 33
+      Width = 514
       Anchors = [akTop, akLeft, akRight]
       BorderSpacing.Left = 12
       BorderSpacing.Top = 6
       BorderSpacing.Bottom = 6
-      ItemHeight = 15
+      ItemHeight = 0
       TabOrder = 3
       Text = 'ExecuteAfterCommandComboBox'
     end
@@ -123,14 +123,13 @@
       AnchorSideRight.Side = asrBottom
       AnchorSideBottom.Control = ExecuteAfterCommandComboBox
       AnchorSideBottom.Side = asrBottom
-      Left = 708
-      Height = 23
-      Top = 31
+      Left = 710
+      Height = 31
+      Top = 33
       Width = 23
       Anchors = [akTop, akRight, akBottom]
       BorderSpacing.Right = 6
       Caption = '…'
-      OnClick = CompCmdBrowseButtonClick
       TabOrder = 4
     end
     object ExecAfterParsersLabel: TLabel
@@ -137,12 +136,12 @@
       AnchorSideLeft.Control = ExecuteAfterGroupBox
       AnchorSideTop.Control = ExecAfterParsersCheckListBox
       Left = 6
-      Height = 15
-      Top = 63
-      Width = 114
+      Height = 19
+      Top = 73
+      Width = 135
       BorderSpacing.Left = 6
       BorderSpacing.Top = 3
-      Caption = 'ExecAfterParsersLabel'
+      Caption = 'ExecAfterParserLabel'
       ParentColor = False
     end
     object ExecAfterParsersCheckListBox: TCheckListBox
@@ -150,14 +149,78 @@
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteAfterCommandComboBox
       AnchorSideTop.Side = asrBottom
-      Left = 126
-      Height = 80
-      Top = 60
+      Left = 147
+      Height = 96
+      Top = 70
       Width = 180
       BorderSpacing.Around = 6
       ItemHeight = 0
       TabOrder = 5
+      TopIndex = -1
     end
+    object chkExecAfterRunAsUser: TCheckBox
+      AnchorSideLeft.Control = ExecAfterParsersCheckListBox
+      AnchorSideLeft.Side = asrBottom
+      AnchorSideTop.Control = ExecAfterParsersLabel
+      Left = 345
+      Height = 21
+      Top = 79
+      Width = 163
+      BorderSpacing.Left = 12
+      BorderSpacing.Around = 6
+      Caption = 'Run as a different user'
+      Enabled = False
+      TabOrder = 6
+    end
+    object ExecuteAfterRunAsUserComboBox: TComboBox
+      AnchorSideLeft.Control = ExecAfterRunAsUserLabel
+      AnchorSideLeft.Side = asrBottom
+      AnchorSideTop.Control = ExecAfterRunAsUserLabel
+      AnchorSideTop.Side = asrCenter
+      AnchorSideRight.Control = ExecuteAfterCommandComboBox
+      AnchorSideRight.Side = asrBottom
+      Left = 419
+      Height = 31
+      Top = 100
+      Width = 291
+      Anchors = [akTop, akLeft, akRight]
+      BorderSpacing.Left = 6
+      BorderSpacing.Top = 6
+      BorderSpacing.Bottom = 6
+      Enabled = False
+      ItemHeight = 0
+      TabOrder = 7
+    end
+    object ExecAfterRunAsUserLabel: TLabel
+      AnchorSideLeft.Control = chkExecAfterRunAsUser
+      AnchorSideTop.Control = chkExecAfterRunAsUser
+      AnchorSideTop.Side = asrBottom
+      Left = 345
+      Height = 19
+      Top = 106
+      Width = 68
+      BorderSpacing.Top = 6
+      Caption = 'User name'
+      Enabled = False
+      ParentColor = False
+    end
+    object ExecAfterRunAsUserButton: TButton
+      AnchorSideTop.Control = ExecuteAfterRunAsUserComboBox
+      AnchorSideRight.Control = ExecuteAfterGroupBox
+      AnchorSideRight.Side = asrBottom
+      AnchorSideBottom.Control = ExecuteAfterRunAsUserComboBox
+      AnchorSideBottom.Side = asrBottom
+      Left = 710
+      Height = 31
+      Top = 100
+      Width = 23
+      Anchors = [akTop, akRight, akBottom]
+      BorderSpacing.Right = 6
+      Caption = '…'
+      Enabled = False
+      OnClick = ExecAfterRunAsUserButtonClick
+      TabOrder = 8
+    end
   end
   object grpCompiler: TGroupBox
     AnchorSideLeft.Control = Owner
@@ -166,23 +229,23 @@
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
     Left = 0
-    Height = 80
-    Top = 197
+    Height = 90
+    Top = 225
     Width = 741
     Anchors = [akTop, akLeft, akRight]
     AutoSize = True
     BorderSpacing.Top = 6
     Caption = 'grpCompiler'
-    ClientHeight = 60
-    ClientWidth = 737
+    ClientHeight = 70
+    ClientWidth = 739
     TabOrder = 2
     object lblRunIfCompiler: TLabel
       AnchorSideLeft.Control = grpCompiler
       AnchorSideTop.Control = grpCompiler
       Left = 6
-      Height = 15
+      Height = 19
       Top = 6
-      Width = 90
+      Width = 104
       BorderSpacing.Around = 6
       Caption = 'lblRunIfCompiler'
       ParentColor = False
@@ -192,9 +255,9 @@
       AnchorSideTop.Control = cobCompiler
       AnchorSideTop.Side = asrCenter
       Left = 6
-      Height = 15
-      Top = 35
-      Width = 62
+      Height = 19
+      Top = 39
+      Width = 70
       BorderSpacing.Around = 6
       Caption = 'lblCompiler'
       ParentColor = False
@@ -203,12 +266,12 @@
       AnchorSideLeft.Control = lblRunIfCompiler
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = grpCompiler
-      Left = 126
-      Height = 19
+      Left = 146
+      Height = 21
       Top = 6
-      Width = 133
+      Width = 151
       BorderSpacing.Left = 30
-      BorderSpacing.Top = 6
+      BorderSpacing.Around = 6
       Caption = 'chkCompilerCompile'
       TabOrder = 0
     end
@@ -216,10 +279,10 @@
       AnchorSideLeft.Control = chkCompilerCompile
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = grpCompiler
-      Left = 289
-      Height = 19
+      Left = 327
+      Height = 21
       Top = 6
-      Width = 115
+      Width = 132
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkCompilerBuild'
@@ -229,10 +292,10 @@
       AnchorSideLeft.Control = chkCompilerBuild
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = grpCompiler
-      Left = 434
-      Height = 19
+      Left = 489
+      Height = 21
       Top = 6
-      Width = 109
+      Width = 125
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkCompilerRun'
@@ -244,15 +307,15 @@
       AnchorSideTop.Control = chkCompilerCompile
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = BrowseCompilerButton
-      Left = 80
-      Height = 23
-      Top = 31
-      Width = 628
+      Left = 88
+      Height = 31
+      Top = 33
+      Width = 622
       Anchors = [akTop, akLeft, akRight]
       BorderSpacing.Left = 12
       BorderSpacing.Top = 6
       BorderSpacing.Bottom = 6
-      ItemHeight = 15
+      ItemHeight = 0
       TabOrder = 3
       Text = 'cobCompiler'
     end
@@ -262,14 +325,13 @@
       AnchorSideRight.Side = asrBottom
       AnchorSideBottom.Control = cobCompiler
       AnchorSideBottom.Side = asrBottom
-      Left = 708
-      Height = 23
-      Top = 31
+      Left = 710
+      Height = 31
+      Top = 33
       Width = 23
       Anchors = [akTop, akRight, akBottom]
       BorderSpacing.Right = 6
       Caption = '…'
-      OnClick = CompCmdBrowseButtonClick
       ParentShowHint = False
       ShowHint = True
       TabOrder = 4
@@ -282,23 +344,23 @@
     AnchorSideRight.Control = Owner
     AnchorSideRight.Side = asrBottom
     Left = 0
-    Height = 166
-    Top = 25
+    Height = 192
+    Top = 27
     Width = 741
     Anchors = [akTop, akLeft, akRight]
     AutoSize = True
     BorderSpacing.Top = 6
     Caption = 'ExecuteBeforeGroupBox'
-    ClientHeight = 146
-    ClientWidth = 737
+    ClientHeight = 172
+    ClientWidth = 739
     TabOrder = 1
     object lblRunIfExecBefore: TLabel
       AnchorSideLeft.Control = ExecuteBeforeGroupBox
       AnchorSideTop.Control = ExecuteBeforeGroupBox
       Left = 6
-      Height = 15
+      Height = 19
       Top = 6
-      Width = 98
+      Width = 120
       BorderSpacing.Around = 6
       Caption = 'lblRunIfExecBefore'
       ParentColor = False
@@ -308,9 +370,9 @@
       AnchorSideTop.Control = ExecuteBeforeCommandComboBox
       AnchorSideTop.Side = asrCenter
       Left = 6
-      Height = 15
-      Top = 35
-      Width = 159
+      Height = 19
+      Top = 39
+      Width = 189
       BorderSpacing.Around = 6
       Caption = 'ExecuteBeforeCommandLabel'
       ParentColor = False
@@ -319,10 +381,10 @@
       AnchorSideLeft.Control = lblRunIfExecBefore
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteBeforeGroupBox
-      Left = 134
-      Height = 19
+      Left = 156
+      Height = 21
       Top = 6
-      Width = 141
+      Width = 167
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecBeforeCompile'
@@ -332,10 +394,10 @@
       AnchorSideLeft.Control = chkExecBeforeCompile
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteBeforeGroupBox
-      Left = 305
-      Height = 19
+      Left = 353
+      Height = 21
       Top = 6
-      Width = 123
+      Width = 148
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecBeforeBuild'
@@ -345,10 +407,10 @@
       AnchorSideLeft.Control = chkExecBeforeBuild
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteBeforeGroupBox
-      Left = 458
-      Height = 19
+      Left = 531
+      Height = 21
       Top = 6
-      Width = 117
+      Width = 141
       BorderSpacing.Left = 24
       BorderSpacing.Around = 6
       Caption = 'chkExecBeforeRun'
@@ -360,15 +422,15 @@
       AnchorSideTop.Control = chkExecBeforeCompile
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = ExecBeforeBrowseButton
-      Left = 177
-      Height = 23
-      Top = 31
-      Width = 531
+      Left = 207
+      Height = 31
+      Top = 33
+      Width = 503
       Anchors = [akTop, akLeft, akRight]
       BorderSpacing.Left = 12
       BorderSpacing.Top = 6
       BorderSpacing.Bottom = 6
-      ItemHeight = 15
+      ItemHeight = 0
       TabOrder = 3
       Text = 'ExecuteBeforeCommandComboBox'
     end
@@ -379,22 +441,21 @@
       AnchorSideRight.Side = asrBottom
       AnchorSideBottom.Control = ExecuteBeforeCommandComboBox
       AnchorSideBottom.Side = asrBottom
-      Left = 708
-      Height = 23
-      Top = 31
+      Left = 710
+      Height = 31
+      Top = 33
       Width = 23
       Anchors = [akTop, akRight, akBottom]
       BorderSpacing.Right = 6
       Caption = '…'
-      OnClick = CompCmdBrowseButtonClick
       TabOrder = 4
     end
     object ExecBeforeParsersLabel: TLabel
       AnchorSideTop.Control = ExecBeforeParsersCheckListBox
       Left = 6
-      Height = 15
-      Top = 63
-      Width = 122
+      Height = 19
+      Top = 73
+      Width = 152
       BorderSpacing.Left = 6
       BorderSpacing.Top = 3
       Caption = 'ExecBeforeParsersLabel'
@@ -405,13 +466,14 @@
       AnchorSideLeft.Side = asrBottom
       AnchorSideTop.Control = ExecuteBeforeCommandComboBox
       AnchorSideTop.Side = asrBottom
-      Left = 134
-      Height = 80
-      Top = 60
+      Left = 164
+      Height = 96
+      Top = 70
       Width = 180
       BorderSpacing.Around = 6
       ItemHeight = 0
       TabOrder = 5
+      TopIndex = -1
     end
   end
 end
Index: ide/frames/compiler_compilation_options.pas
===================================================================
--- ide/frames/compiler_compilation_options.pas	(revision 64770)
+++ ide/frames/compiler_compilation_options.pas	(working copy)
@@ -26,8 +26,11 @@
 
   TCompilerCompilationOptionsFrame = class(TAbstractIDEOptionsEditor)
     BrowseCompilerButton: TButton;
+    chkExecAfterRunAsUser: TCheckBox;
     ExecAfterParsersCheckListBox: TCheckListBox;
     ExecAfterParsersLabel: TLabel;
+    ExecAfterRunAsUserButton: TButton;
+    ExecAfterRunAsUserLabel: TLabel;
     ExecBeforeBrowseButton: TButton;
     chkCompilerBuild: TCheckBox;
     chkCompilerCompile: TCheckBox;
@@ -43,6 +46,7 @@
     ExecAfterBrowseButton: TButton;
     ExecBeforeParsersCheckListBox: TCheckListBox;
     ExecuteAfterCommandComboBox: TComboBox;
+    ExecuteAfterRunAsUserComboBox: TComboBox;
     ExecuteAfterCommandLabel: TLabel;
     ExecuteAfterGroupBox: TGroupBox;
     ExecuteBeforeCommandComboBox: TComboBox;
@@ -55,6 +59,7 @@
     lblRunIfExecAfter: TLabel;
     lblRunIfExecBefore: TLabel;
     procedure CompCmdBrowseButtonClick(Sender: TObject);
+    procedure ExecAfterRunAsUserButtonClick(Sender: TObject);
   private
     procedure ReadSettingsParsers(ToolOpts: TCompilationToolOptions;
       Cmb: TCheckListBox);
@@ -72,6 +77,9 @@
 
 {$R *.lfm}
 
+uses
+  RunExecuteAfterAsUser;
+
 { TCompilerCompilationOptionsFrame }
 
 procedure TCompilerCompilationOptionsFrame.CompCmdBrowseButtonClick(
@@ -174,6 +182,12 @@
   end;
 end;
 
+procedure TCompilerCompilationOptionsFrame.ExecAfterRunAsUserButtonClick(
+  Sender: TObject);
+begin
+
+end;
+
 procedure TCompilerCompilationOptionsFrame.ReadSettingsParsers(
   ToolOpts: TCompilationToolOptions; Cmb: TCheckListBox);
 var
@@ -370,6 +384,17 @@
   chkExecAfterCompile.Visible := IsProj;
   chkExecAfterBuild.Visible := IsProj;
   chkExecAfterRun.Visible := IsProj;
+
+// Control UI elements visibility and enabled state depending on whether the OS
+// can run as a different user and the prerequisites have been met. MarkMLl
+
+  chkExecAfterRunAsUser.Visible := RunExecuteAfterAsUser.HasDifferentUser();
+  ExecuteAfterRunAsUserComboBox.Visible := chkExecAfterRunAsUser.Visible;
+  ExecAfterRunAsUserLabel.Visible := chkExecAfterRunAsUser.Visible;
+  chkExecAfterRunAsUser.Enabled := RunExecuteAfterAsUser.HasPrequisites();
+  ExecuteAfterRunAsUserComboBox.Enabled := chkExecAfterRunAsUser.Enabled;
+  ExecAfterRunAsUserLabel.Enabled := chkExecAfterRunAsUser.Enabled;
+
   ReadSettingsParsers(Options.ExecuteAfter,ExecAfterParsersCheckListBox);
 end;
 
@@ -418,7 +443,15 @@
   Options.ExecuteAfter.Command := ExecuteAfterCommandComboBox.Text;
   HL := InputHistories.HistoryLists.GetList('BuildExecAfter',true,rltCaseSensitive);
   HL.Assign(ExecuteAfterCommandComboBox.Items);
-  HL.Push(Options.ExecuteAfter.Command);
+
+// Optionally augment the command to run as different user. MarkMLl
+
+  if not chkExecAfterRunAsUser.Checked then
+    HL.Push(Options.ExecuteAfter.Command)
+  else
+    HL.Push(RunExecuteAfterAsUser.Prefix(Options.ExecuteAfter.Command,
+                                        Trim(ExecuteAfterRunAsUserComboBox.Text)));
+
   WriteSettingsParsers(Options.ExecuteAfter,ExecAfterParsersCheckListBox);
   if Options.ExecuteAfter is TProjectCompilationToolOptions then
     Options.ExecuteAfter.CompileReasons :=
runas2.diff (17,547 bytes)   

Issue History

Date Modified Username Field Change
2021-03-09 17:10 Mark Morgan Lloyd New Issue
2021-03-09 17:10 Mark Morgan Lloyd File Added: runas.diff
2021-03-11 12:17 Mattias Gaertner Note Added: 0129568
2021-03-12 08:24 Juha Manninen Assigned To => Mattias Gaertner
2021-03-12 08:24 Juha Manninen Status new => feedback
2021-03-12 08:24 Juha Manninen LazTarget => -
2021-03-13 09:28 Mark Morgan Lloyd Note Added: 0129623
2021-03-13 09:28 Mark Morgan Lloyd Status feedback => assigned
2021-03-13 11:58 Mattias Gaertner Note Added: 0129626
2021-03-13 18:33 Mark Morgan Lloyd Note Added: 0129635
2021-03-13 18:40 Mark Morgan Lloyd Note Edited: 0129635 View Revisions
2021-03-16 16:56 Mark Morgan Lloyd Note Added: 0129714
2021-03-16 16:56 Mark Morgan Lloyd File Added: runexecuteafterasuser.pas
2021-03-16 16:56 Mark Morgan Lloyd File Added: runas2.diff