// 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

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

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

#include <execp.h>


//  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)
{

  _error = 0;
  _exitcode =  0;

  // save cwd
  save_dir();


#if XVT_OS == XVT_OS_DOS

  // ems swap
  setems(1);
  // *** BLinker support; uncomment as needed
  //  BLIUNHOOK();
  // *******************
  char* s = getenv("TMPDIR");
  if (s == NULL)
    _exitcode = holdev("\\tmp;",0,_path);
  else
    _exitcode = holdev(s,0,_path);
  // *** BLinker support; uncomment as needed
  //  BLREINIT();
  // *******************
  if (!_exitcode)
    _exitcode = childret();
  else
    _exitcode = -_exitcode;
  xvt_escape(XVT_ESC_CH_REFRESH);

#elif XVT_OS == XVT_OS_WIN
  set_cursor(TASK_WIN, CURSOR_WAIT);
  _exitcode = WinExec((char*)_path, SW_SHOW);
  if (_exitcode >= 32)
  {
    if (!async) MainApp()->wait_for(_path);
    _exitcode = 0;
  }  
  else 
    error_box("Impossibile eseguire %s: errore %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)
      _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;
}