// fv 6/10/93                       

#include <stdio.h>

#include <xvt.h>

#if XVT_OS == XVT_OS_SCOUNIX
#include <sys/fcntl.h>
#include <sys/wait.h>
#endif

#include <applicat.h>

#if XVT_OS == XVT_OS_WIN
#include <windows.h>
#endif

#if XVT_OS == XVT_OS_DOS
#include <holdev.h>
#endif

#include <execp.h> 


bool TExternal_app::can_run() const
{                    
#if XVT_OS == XVT_OS_WIN
  const TFixed_string p(_path);           
  const bool clifo = p.find("cg0") == 0 && p.right(2) == "-1";
  const int richieste = clifo ? 50 : 15;
  const int libere = GetFreeSystemResources(GFSR_SYSTEMRESOURCES);
  return libere >= richieste;
#else
  return TRUE;
#endif
}


//  char _path[120];     // app name
//  int  _error;         // last error
//  int  _exitcode;      // last exit code
//  int  _count;         // count of calls returning 0
//  int error()    { return _error};
//  int exitcode() { return _exitcode};
//  int count()    { return _count; };

int TExternal_app::run(bool async, bool iconized)
{
  TString256 path(_path);
  if (iconized)
    path << " -icon"; 
  path << " -u" << main_app().user();
  _error = 0;
  _exitcode =  0;

  // save cwd
  save_dir();

#if XVT_OS == XVT_OS_WIN
  if (!can_run())
  {
    error_box("Le risorse di Windows sono quasi esaurite:\n"
              "impossibile eseguire %s", (const char*)_path);
    _exitcode = 8;
  }
  
  if (_exitcode == 0)
  {              
    set_cursor(TASK_WIN, CURSOR_WAIT);
    
    const UINT sh = iconized ? SW_SHOWMINIMIZED : SW_SHOW;
    _exitcode = WinExec((char*)(const char*)path, sh);
    
    if (_exitcode >= 32)
    {
      if (!async) main_app().wait_for(_path);
      _exitcode = 0;
    }  
    else 
    {
      if (_exitcode == 16)
        error_box("'%s' e' gia' in esecuzione", (const char*)_path);
      else
        error_box("Impossibile eseguire '%s':\nErrore %d", (const char*)_path, _exitcode);
    }  
    
    set_cursor(TASK_WIN, CURSOR_ARROW);
  }
#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_escape(XVT_ESC_CH_REFRESH);

#endif

  // restore cwd
  restore_dir();

  // update counts
  if (_exitcode == 0)
    _count++;
  return _exitcode;
}

TExternal_app::TExternal_app(const char* p)
{
  _path =  p;
  _count = 0;
  _error = 0;
  _exitcode =  0;
}
