static unsigned segment_exists(struct vpu *vpu, unsigned seg)
{
  unsigned n;
  if(seg < vpu->data_count) return vpu->data_size;
  for(n = vpu->dynsegment_count;n--;)
    if(vpu->dynsegments[n].segment == seg)
      return vpu->dynsegments[n].length;
  return 0;
}

static void segfault(struct vpu *vpu)
{
  vpu->flags.datav = 1;
  putstr(segfaulterror);
  send_vpu_signal(vpu, SIGSEGV);
}

static unsigned char memory_allowed(struct vpu *vpu, unsigned long offset)
{
  unsigned n;

  if((offset >> 16) || (unsigned short)offset >= segment_exists(vpu, vpu->data_segment))
  {
    segfault(vpu);
    return 0;
  }

  return 1;
}

static int is_subpath(char *path, char *iwd, char *cwd)
{
  char oldcwd[MAX_PATH+1];
  char newcwd[MAX_PATH+1];
  unsigned old_drive;
  unsigned total_drives;
  int rc;
  struct find_t fileinfo;
  char *ptr;
  char olddl;
//  char parentdir[] = "..";


  if(!*path) return 1;

  if(path[1] == ':')
  {
    if((path[0]&0x1F) != (iwd[0]&0x1F)) return 0;
  }

  getcwd(oldcwd, MAX_PATH);
  old_drive = oldcwd[0] & 0x1F;
  _dos_setdrive(iwd[0]&0x1F, &total_drives);

  if(*cwd ? chdir(cwd) : chdir(iwd))
  {
    rc = 0;
    goto end;
  }

  ptr = strrchr(path, '/');
  if(!ptr) ptr = strrchr(path, '\\');
/*  if(!ptr && strcmp(path, parentdir))
  {
    rc = 1;
    goto end;
  }*/

  if(!findfirst(path, 0xFF, &fileinfo))
  {
    if(!(fileinfo.attrib & _A_SUBDIR))
    {
      if(ptr)
      {
        olddl = *ptr;
        *ptr = 0;
      }
      else
      {
        chdir(oldcwd);
        rc = 1;
        goto end;
      }
    }
    else goto noptr;
  }
  else noptr:ptr = 0;

  if(chdir(path))
    rc = 0;
  else
  {
    getcwd(newcwd, MAX_PATH);
    if(iwd[0] != newcwd[0]) rc = 0;
    else if(memcmp(iwd, newcwd, strlen(iwd))) rc = 0;
    else rc = 1;
  }
  if(ptr) *ptr = olddl;
  end:
  _dos_setdrive(old_drive, &total_drives);
  chdir(oldcwd);

  return rc;
}
