Supporto cambio di direttorio Supporto applicazioni spezzate git-svn-id: svn://10.65.10.50/trunk@4538 c028cbd2-c16b-5b4b-a496-9718f37d4682
353 lines
8.9 KiB
C++
Executable File
353 lines
8.9 KiB
C++
Executable File
#include <stdio.h>
|
|
|
|
#define STRICT
|
|
#define XVT_INCL_NATIVE
|
|
#include <xvt.h>
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
#include <toolhelp.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#endif
|
|
|
|
#if XVT_OS == XVT_OS_SCOUNIX
|
|
#include <sys/fcntl.h>
|
|
#include <sys/wait.h>
|
|
#endif
|
|
|
|
#include <hlapi_c.h>
|
|
|
|
#include <applicat.h>
|
|
#include <execp.h>
|
|
#include <prefix.h>
|
|
#include <utility.h>
|
|
#include <window.h>
|
|
#include <extcdecl.h>
|
|
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Controlla se il processo puo' essere eseguito
|
|
//
|
|
// @rdesc Ritorna i seguenti valori:
|
|
//
|
|
// @flag TRUE | Se l'applicazione puo' essere eseguita
|
|
// @flag FALSE | Se l'applicazione non puo' essere eseguita
|
|
bool TExternal_app::can_run() const
|
|
|
|
// @comm Se si opera sotto Windows si controlla se vi sono risorse necessarie
|
|
// per l'esecuzione del processo, altrimenti viene tornato sempre TRUE.
|
|
{
|
|
#if XVT_OS == XVT_OS_WIN
|
|
const TFixed_string p(_path);
|
|
const bool big = p.find("cg0") == 0 && p.right(2) == "-1";
|
|
const int richieste = big ? 50 : 15;
|
|
const int libere = GetFreeSystemResources(GFSR_SYSTEMRESOURCES);
|
|
return libere >= richieste;
|
|
#else
|
|
return TRUE;
|
|
#endif
|
|
}
|
|
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Esegue il processo
|
|
//
|
|
// @rdesc Ritorna il codice di uscita del processo (-1 in caso di errore).
|
|
word TExternal_app::run(
|
|
bool async, // @parm Per eseguire il processo in parallelo (default FALSE)
|
|
bool utente) // @parm Permette di inserire il nome dell'utente nella riga
|
|
// di comando(default TRUE)
|
|
|
|
// @comm Se <p asyn> e' FALSE aspetta che termini il processo in esecuzione prima di iniziare il nuovo
|
|
|
|
{
|
|
TFilename path(_path);
|
|
TString name(path.name());
|
|
int p = name.find(' ');
|
|
|
|
if (p >=0)
|
|
name = name.left(p);
|
|
const bool our_app = name.len() > 2 && (isalpha(name[0]) || name[0] == '7') &&
|
|
isalnum(name[1]) && isdigit(name[2]);
|
|
|
|
if (!our_app)
|
|
utente = FALSE;
|
|
if (utente)
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32
|
|
path << " /u" << user();
|
|
#else
|
|
path << " -u" << user();
|
|
#endif
|
|
|
|
_error = 0;
|
|
_exitcode = 0;
|
|
|
|
// save cwd
|
|
xvt_fsys_save_dir();
|
|
|
|
const TFilename dir(path.path());
|
|
|
|
if (dir.not_empty())
|
|
{
|
|
DIRECTORY d;
|
|
|
|
if (xvt_fsys_convert_str_to_dir((char *) (const char *) dir, &d))
|
|
xvt_fsys_set_dir(&d);
|
|
}
|
|
if (our_app)
|
|
{
|
|
TString parms(_path);
|
|
TString new_suffix;
|
|
int p = parms.find(' ');
|
|
|
|
if (p < 0)
|
|
{
|
|
parms = "";
|
|
new_suffix = "_0";
|
|
}
|
|
else
|
|
{
|
|
parms = parms.mid(p + 1);
|
|
p = parms.find(' ');
|
|
if (p >= 0)
|
|
new_suffix = parms.left(p);
|
|
else new_suffix = parms;
|
|
if (new_suffix[0] == '-') new_suffix[0] = '_';
|
|
else new_suffix = "__";
|
|
}
|
|
|
|
TFilename newpath(dir);
|
|
|
|
if (newpath.not_empty())
|
|
newpath << '/';
|
|
newpath << name << new_suffix;
|
|
newpath.ext("exe");
|
|
if (fexist(newpath))
|
|
{
|
|
newpath.ext("");
|
|
newpath << parms;
|
|
path = newpath;
|
|
if (utente)
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32
|
|
path << " /u" << user();
|
|
#else
|
|
path << " -u" << user();
|
|
#endif
|
|
|
|
}
|
|
}
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32
|
|
if (can_run())
|
|
{
|
|
main_app().begin_wait();
|
|
#if XVT_OS == XVT_OS_WIN
|
|
HL_LOGOUT();
|
|
_exitcode = WinExec((char*)(const char*)path, SW_SHOW);
|
|
|
|
if (_exitcode >= 32)
|
|
{
|
|
if (!async)
|
|
{
|
|
TTemp_window tw(TASK_WIN);
|
|
if (utente)
|
|
{
|
|
tw.iconize();
|
|
tw.deactivate();
|
|
}
|
|
|
|
HTASK child = NULL;
|
|
TASKENTRY te; te.dwSize = sizeof(TASKENTRY);
|
|
for (bool ok = TaskFirst(&te); ok; ok = TaskNext(&te))
|
|
if (te.hInst == (HINSTANCE)_exitcode)
|
|
{
|
|
child = te.hTask;
|
|
break;
|
|
}
|
|
|
|
// Warning! child could be NULL if you run that beast called Foxpro
|
|
|
|
main_app().wait_for((word)child);
|
|
for (byte i = 0; main_app().waiting() == (word)child; i++)
|
|
{
|
|
// Esegue il controllo solo ogni 256 cicli
|
|
if (i == 0 && ok && TaskFindHandle(&te, child) == FALSE)
|
|
{
|
|
main_app().wake_up(); // Annulla attesa del processo
|
|
break;
|
|
}
|
|
xvt_app_process_pending_events();
|
|
}
|
|
|
|
if (utente)
|
|
{
|
|
tw.maximize();
|
|
tw.activate();
|
|
xvt_app_process_pending_events();
|
|
}
|
|
}
|
|
xvt_statbar_refresh();
|
|
}
|
|
#else
|
|
STARTUPINFO start;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
start.cb = sizeof(start);
|
|
start.lpReserved = start.lpDesktop = start.lpTitle = NULL;
|
|
start.dwX = start.dwY = start.dwXSize = start.dwYSize = CW_USEDEFAULT;
|
|
start.dwXCountChars = start.dwYCountChars = start.dwFillAttribute = 0L;
|
|
start.dwFlags = STARTF_USESHOWWINDOW;
|
|
start.wShowWindow = SW_SHOW ;
|
|
start.cbReserved2 = 0;
|
|
start.lpReserved2 = NULL;
|
|
start.hStdInput = NULL;
|
|
start.hStdOutput = NULL ;
|
|
start.hStdError = NULL;
|
|
BOOL started = CreateProcess(NULL,(char*)(const char*)path, NULL, NULL, FALSE, 0,
|
|
NULL, NULL, &start, &pi);
|
|
if (started)
|
|
{
|
|
HANDLE hProcess = pi.hProcess;
|
|
|
|
if (!async)
|
|
{
|
|
TTemp_window tw(TASK_WIN);
|
|
if (utente)
|
|
{
|
|
tw.iconize();
|
|
tw.deactivate();
|
|
}
|
|
if (WaitForSingleObject(hProcess, INFINITE) != 0xFFFFFFFF)
|
|
{
|
|
unsigned long exitcode;
|
|
if (GetExitCodeProcess(hProcess, &exitcode))
|
|
_exitcode = (int) exitcode;
|
|
else
|
|
_exitcode = -2;
|
|
}
|
|
if (utente)
|
|
{
|
|
tw.maximize();
|
|
tw.activate();
|
|
}
|
|
}
|
|
else
|
|
_exitcode = 0;
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(hProcess);
|
|
}
|
|
else _exitcode = -1;
|
|
|
|
#endif
|
|
main_app().end_wait();
|
|
} else _exitcode = 1;
|
|
|
|
#if XVT_OS == XVT_OS_WIN
|
|
_error = _exitcode;
|
|
switch (_exitcode)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
error_box("Risorse insufficienti per eseguire '%s'", (const char*)_path); break;
|
|
case 2:
|
|
case 3:
|
|
error_box("Impossibile trovare '%s'", (const char*)_path); break;
|
|
case 16:
|
|
error_box("'%s' e' gia' in esecuzione", (const char*)_path); break;
|
|
default:
|
|
if (_exitcode < 32 && _exitcode != 8)
|
|
error_box("Impossibile eseguire '%s':\nErrore %u", (const char*)_path, _exitcode);
|
|
else
|
|
{
|
|
if (_exitcode != 8) _error = 0;
|
|
_exitcode = 0;
|
|
}
|
|
break;
|
|
}
|
|
#else
|
|
switch (_exitcode)
|
|
{
|
|
case -2:
|
|
error_box("Impossibile ricevere il valore di ritorno da '%s':\nErrore %ld", (const char*)_path, GetLastError()); break;
|
|
case -1:
|
|
error_box("Impossibile eseguire '%s':\nErrore %ld", (const char*)_path, GetLastError()); break;
|
|
case 8:
|
|
error_box("Risorse insufficienti per eseguire '%s'", (const char*)_path); break;
|
|
case 0:
|
|
break;
|
|
default:
|
|
error_box("Valore di ritorno di '%s':\n %ld", (const char*)_path, _exitcode); break;
|
|
}
|
|
#endif
|
|
#else
|
|
|
|
switch (fork())
|
|
{
|
|
case -1:
|
|
_error = errno;
|
|
_exitcode = -1;
|
|
break;
|
|
case 0:
|
|
const char* s = strdup(path);
|
|
char* p = strchr(s, ' ');
|
|
if (p) *p = '\0';
|
|
const char* pathn = strdup(s);
|
|
const char* args[21];
|
|
int i = 0;
|
|
args[i++] = pathn;
|
|
while ((i < 20) && (p))
|
|
{
|
|
s = p + 1;
|
|
p = strchr(s, ' ');
|
|
if (p) *p = '\0';
|
|
args[i++] = strdup(s);
|
|
}
|
|
args[i] = NULL;
|
|
for (i = 3; i < _NFILE; i++) fcntl(i,F_SETFD,1);
|
|
// execvp( path, NULL);
|
|
execvp ( pathn , args );
|
|
exit ( -1 );
|
|
default:
|
|
if(wait(&_exitcode) == -1)
|
|
{
|
|
error_box("Impossibile eseguire '%s':\nErrore %d", (const char*)_path, _exitcode);
|
|
_exitcode = -1;
|
|
}
|
|
else _exitcode = _exitcode >> 8;
|
|
break;
|
|
}
|
|
_error = errno;
|
|
xvt_app_escape(XVT_ESC_CH_REFRESH);
|
|
|
|
#endif
|
|
|
|
// restore cwd
|
|
xvt_fsys_restore_dir();
|
|
|
|
// update counts
|
|
if (_exitcode == 0)
|
|
_count++;
|
|
#if XVT_OS == XVT_OS_WIN
|
|
// Ignora volutamente il return code da HL_LOGIN(). Se va bene riprende il posto
|
|
// altrimenti fa lo stesso. Infatti puo' capitare con una chiave di rete, che
|
|
// nel lasso di tempo trascorso dalla HL_LOGOUT() dell'applicazione chiamata,
|
|
// a questa HL_LOGIN() [approssimativamente qualche decimo di secondo], qualche altro
|
|
// programma si inserisca, occupando magari anche l'ultimo posto disponibile.
|
|
// Quindi se si verificasse tale sfigatissima condizione, sicuramente
|
|
// non ci saranno piu' posti liberi nell'HL_server: il programma comunque non
|
|
// puo' interrompersi a meta'; ecco perche il valore di ritorno di HL_LOGIN viene
|
|
// ignorato.
|
|
HL_LOGIN(ModAd, DONT_CARE, REFKEY, VERKEY);
|
|
#endif
|
|
return _exitcode;
|
|
}
|
|
|
|
TExternal_app::TExternal_app(const char* p)
|
|
{
|
|
_path = p;
|
|
_count = 0;
|
|
_error = 0;
|
|
_exitcode = 0;
|
|
}
|