execve+GUI приложения [Решено]

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

execve+GUI приложения [Решено]

Сообщение coyot.rush » 30.03.2011 23:50:43

man execve http://www.opennet.ru/man.shtml?topic=execve&category=2&russian=
С этой функцией у меня возникли проблемы , GUI приложения отказываются нормально работать (испытывал на mplayer ) возникают сбои ( mplayer выводит видео через fbdev). В тоже время консольные программы работают нормально

Код "пускателя"
Код: Выделить всё
program applaunch;

{$mode objfpc}{$H+}

uses
  {$IFDEF Linux}
  cthreads,
  {$ENDIF}
  Classes,sysutils, uapplaunch;
var
path:string;
data:portb_env;
id:integer;
begin
path:=GetCurrentDirEx+PathDelim+'settings.ini';

writeln('path='+path);

if fileexists(path) then
begin
  data:=ReadAppData(Path);
  data.curpath:=GetCurrentDirEx;

  writeln('data.curpath+PathDelim+data.namebin='+data.curpath+PathDelim+data.namebin);
  writeln('data.curpath+PathDelim+data.libdir='+data.curpath+PathDelim+data.libdir);
  writeln('data.curpath+PathDelim+data.homedir='+data.curpath+PathDelim+data.homedir);

  id:=RunApp(
  data.curpath+PathDelim+data.namebin,
  data.curpath+PathDelim+data.libdir,
  data.curpath+PathDelim+data.homedir,
  data.locale)
end
else
begin
  writeln('Settings file not found')
end;
while CheckRunApp(id)=true do
  begin
   Sleep(100);
  end;

CloseAppDesc(id);

writeln('applaunch terminated'); 
end.         


Код: Выделить всё
unit uapplaunch;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils,IniFiles,libc;

type

portb_env=record
homedir:string;
curpath:string;
libdir:string;
locale:string;
namebin:string;
end;
function CheckRunApp(id_process:integer): Boolean;
function CloseAppDesc(id_process:integer): Boolean;
function RunApp(PathToBin,PathToLib,HomeDir,LocaleStr:string):integer;
function ReadAppData(PathToDesctopFile: string):portb_env;
function OverWriteEnv(PathToLib,HomeDir,LocaleStr:string):PPchar;
function GetParams():PPChar;
function GetCurrentDirEx():string;
implementation


function CheckRunApp(id_process:integer): boolean;
begin
Result:=DirectoryExists('/proc/'+inttostr(id_process));
end;


function CloseAppDesc(id_process:integer): Boolean;
begin
Result:=True;
//0-running
//-1-not running
if waitpid(id_process, nil, WNOHANG) = -1 then
begin
Result := False;
end;
end;



function GetCurrentDirEx():string;
begin
Result:=ExtractFileDir(ParamStr(0));
end;

function RunApp(PathToBin, PathToLib, HomeDir, LocaleStr: string): integer;

var
ChildPid:integer;
begin
ChildPid:=libc.fork;
case ChildPid of
-1:
  begin
   writeln('error fork')
  end;
0:
  begin
   execve(PChar(PathToBin),GetParams,OverWriteEnv(PathToLib,HomeDir,LocaleStr));
  end;
end;
Result:=ChildPid;
end;


function ReadAppData(PathToDesctopFile: string):portb_env;
var
df:TIniFile;
begin
df:=TIniFile.Create(PathToDesctopFile);
Result.namebin:=df.ReadString('app','namebin','');
Result.libdir:=df.ReadString('app','libdir','');
Result.homedir:=df.ReadString('app','homedir','');
Result.locale:=df.ReadString('app','locale','');
Result.curpath:='';
df.Free;
end;

function OverWriteEnv(PathToLib, HomeDir, LocaleStr: string): PPchar;
var
i,ec:integer;
env_ar__: array of Pchar;
tmpstr:string;
begin
Result:=nil;
ec:=GetEnvironmentVariableCount;
SetLength(env_ar__,ec-1);
if ec=0 then begin exit end;
for i:=0 to ec-1 do
begin
tmpstr:=GetEnvironmentString(i);
if tmpstr='HOME' then begin tmpstr:=HomeDir end;
if tmpstr='LD_LIBRARY_PATH' then begin tmpstr:=PathToLib end;
if tmpstr='LANG' then begin tmpstr:=LocaleStr end;
env_ar__[i]:=Pchar(tmpstr);
end;

env_ar__[ec]:=nil;
GetMem(Result,ec*sizeOf(PChar));
Result:=@env_ar__[0];
end;

function GetParams(): PPChar;
var
ArgArray:  array of PChar;
i:      integer;
parc:integer;
begin
parc:=Paramcount;
writeln('Paramcount='+inttostr(Paramcount));
if parc > 0 then
begin
SetLength(argArray, parc + 2);
Getmem(Result,(parc+2)*SizeOf(Pchar));
argArray[0] := '';
for i := 1 to parc do
begin
  argArray[i] :=Pchar(ParamStr(i));
end;
argArray[parc+1] := nil;
Result := @argArray[0];
end
else
begin
SetLength(argArray, 2);
argArray[0] := '';
argArray[1] := nil;
Getmem(Result,2*SizeOf(Pchar));
Result      := @argArray[0];
end;
end;


end.


PS: Пишу аналог AppRun http://portablelinuxapps.org/

Добавлено спустя 14 часов 42 минуты 12 секунд:
Ошибка явно в функции OverWriteEnv. Неправильная работа с PPchar :oops:
Как правильно передать новые значения переменных окружения в execve?
Переделал так
Код: Выделить всё
function OverWriteEnv(PathToLib, HomeDir, LocaleStr: string): PPchar;
var
i,ec:integer;
env_ar__: array of Pchar;
tmpstr:string;
OverWrite_LD_LIBRARY_PATH:Boolean;
begin
Result:=nil;
ec:=GetEnvironmentVariableCount;
SetLength(env_ar__,ec+1);
if ec=0 then begin exit end;
OverWrite_LD_LIBRARY_PATH:=False;
for i:=0 to ec-1 do
begin
tmpstr:=GetEnvironmentString(i);
if pos('HOME=',tmpstr)>0 then
  begin
   tmpstr:='HOME='+HomeDir;
  end;
if pos('LD_LIBRARY_PATH=',tmpstr)>0 then
  begin
   OverWrite_LD_LIBRARY_PATH:=True;
   tmpstr:='LD_LIBRARY_PATH='+PathToLib;
  end;
if (pos('LANG=',tmpstr)>0) and (LocaleStr<>'') then
  begin
   tmpstr:='LANG='+LocaleStr;
  end;
//writeln(tmpstr+'  <>  '+inttostr(i));
env_ar__[i]:=Pchar(tmpstr);
end;
if OverWrite_LD_LIBRARY_PATH=false then
begin
tmpstr:='LD_LIBRARY_PATH='+PathToLib;
env_ar__[ec]:=Pchar(tmpstr);
GetMem(Result,(ec+1)*sizeOf(PChar));
end else
begin
SetLength(env_ar__,ec);
//env_ar__[ec]:=#0; ???
GetMem(Result,ec*sizeOf(PChar));
end;
Result:=@env_ar__[0];
end;


Добавлено спустя 53 минуты 45 секунд:
Проблема была в том что нужно выделить память под каждый элемент

Код: Выделить всё
function OverWriteEnv(PathToLib, HomeDir, LocaleStr: string): PPchar;
var
i,ec:integer;
env_ar__: array of Pchar;
tmpstr:string;
OverWrite_LD_LIBRARY_PATH:Boolean;
begin
Result:=nil;
ec:=GetEnvironmentVariableCount;
SetLength(env_ar__,ec+2);
if ec=0 then begin exit end;
OverWrite_LD_LIBRARY_PATH:=False;
for i:=0 to ec-1 do
begin
tmpstr:=GetEnvironmentString(i);
if pos('HOME=',tmpstr)>0 then
  begin
   tmpstr:='HOME='+HomeDir;
  end;
if pos('LD_LIBRARY_PATH=',tmpstr)>0 then
  begin
   OverWrite_LD_LIBRARY_PATH:=True;
   tmpstr:='LD_LIBRARY_PATH='+PathToLib;
  end;
if (pos('LANG=',tmpstr)>0) and (LocaleStr<>'') then
  begin
   tmpstr:='LANG='+LocaleStr;
  end;
getmem(env_ar__[i],length(tmpstr));
env_ar__[i]:=Pchar(tmpstr);
//writeln(string(env_ar__[i])+'  <>  '+inttostr(i));

end;
if OverWrite_LD_LIBRARY_PATH=false then
begin
tmpstr:='LD_LIBRARY_PATH='+PathToLib;
env_ar__[ec]:=Pchar(tmpstr);
env_ar__[ec+1]:=nil;
GetMem(Result,(ec+2)*sizeOf(PChar));
end else
begin
SetLength(env_ar__,ec+1);
env_ar__[ec]:=nil;
GetMem(Result,(ec+1)*sizeOf(PChar));
end;
Result:=@env_ar__[0];
end;


Но всё равно работает неправильно вот вывод env запущенного через applaunch
Код: Выделить всё
ORBIT_SOCKETDIR=/tmp...
ORBIT_SOCKETDIR=/tmp...
USERNAME=...
USERNAME=...
USERNAME=...
XDG_SESSION_COOKIE=...
USERNAME=...
PWD=/home/...
GTK_MODULES=canberra-gtk-module
USERNAME=...
PWD=/home/...
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/...
USERNAME=...
PWD=/home/...
PWD=/home/...
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/...
DESKTOP_SESSION=gnome
PWD=/home/...
GNOME_KEYRING_PID=...
LANG=ru_RU.utf8
GNOME_KEYRING_PID=...
DISPLAY=:0.0
LD_LIBRARY_PATH=...
DISPLAY=:0.0
DISPLAY=:0.0
DISPLAY=:0.0
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
DISPLAY=:0.0
LD_LIBRARY_PATH=...
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/....
DISPLAY=:0.0
LD_LIBRARY_PATH=/home/...
COLORTERM=gnome-terminal
LD_LIBRARY_PATH=/home/...
Вложения
env.png
Запуск env через applanch
Последний раз редактировалось coyot.rush 02.05.2011 20:10:46, всего редактировалось 1 раз.
Аватара пользователя
coyot.rush
постоялец
 
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48

Re: execve+GUI приложения

Сообщение coyot.rush » 02.05.2011 20:10:03

Аватара пользователя
coyot.rush
постоялец
 
Сообщения: 309
Зарегистрирован: 14.08.2009 08:59:48


Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 22

Рейтинг@Mail.ru