int
accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
{
  int fd;

#if HAVE_ACCEPT4
# undef accept4
  /* Try the system call first, if it exists.  (We may be running with a glibc
     that has the function but with an older kernel that lacks it.)  */
  {
    /* Cache the information whether the system call really exists.  */
    static int have_accept4_really; /* 0 = unknown, 1 = yes, -1 = no */
    if (have_accept4_really >= 0)
      {
        int result = accept4 (sockfd, addr, addrlen, flags);
        if (!(result < 0 && errno == ENOSYS))
          {
            have_accept4_really = 1;
            return result;
          }
        have_accept4_really = -1;
      }
  }
#endif

  /* Check the supported flags.  */
  if ((flags & ~(SOCK_CLOEXEC | O_TEXT | O_BINARY)) != 0)
    {
      errno = EINVAL;
      return -1;
    }

  fd = accept (sockfd, addr, addrlen);
  if (fd < 0)
    return -1;

#if SOCK_CLOEXEC
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Native Windows API.  */
  if (flags & SOCK_CLOEXEC)
    {
      HANDLE curr_process = GetCurrentProcess ();
      HANDLE old_handle = (HANDLE) _get_osfhandle (fd);
      HANDLE new_handle;
      int nfd;

      if (!DuplicateHandle (curr_process,           /* SourceProcessHandle */
                            old_handle,             /* SourceHandle */
                            curr_process,           /* TargetProcessHandle */
                            (PHANDLE) &new_handle,  /* TargetHandle */
                            (DWORD) 0,              /* DesiredAccess */
                            FALSE,                  /* InheritHandle */
                            DUPLICATE_SAME_ACCESS)) /* Options */
        {
          close (fd);
          errno = EBADF; /* arbitrary */
          return -1;
        }

      /* Closing fd before allocating the new fd ensures that the new fd will
         have the minimum possible value.  */
      close (fd);
      nfd = _open_osfhandle ((intptr_t) new_handle,
                             O_NOINHERIT | (flags & (O_TEXT | O_BINARY)));
      if (nfd < 0)
        {
          CloseHandle (new_handle);
          return -1;
        }
      return nfd;
    }
# else
/* Unix API.  */
  if (flags & SOCK_CLOEXEC)
    {
      int fcntl_flags;

      if ((fcntl_flags = fcntl (fd, F_GETFD, 0)) < 0
          || fcntl (fd, F_SETFD, fcntl_flags | FD_CLOEXEC) == -1)
        {
          int saved_errno = errno;
          close (fd);
          errno = saved_errno;
          return -1;
        }
    }
# endif
#endif

#if O_BINARY
  if (flags & O_BINARY)
    set_binary_mode (fd, O_BINARY);
  else if (flags & O_TEXT)
    set_binary_mode (fd, O_TEXT);
#endif

  return fd;
}
intptr_t ZipPlatform::GetFileSystemHandle(int iDes)
{
	return _get_osfhandle(iDes);
}
Beispiel #3
0
cl_error_t prescan_cb(int fd, const char *type, void *context) {
    struct scan_ctx *sctx = (struct scan_ctx *)context;
    char tmpf[4096];
    instance *inst;
    CLAM_SCAN_INFO si;
    CLAM_ACTION act;
    HANDLE fdhdl;
    DWORD perf, perf2 = 0;

    if(!context) {
	logg("!prescan_cb called with NULL clamav context\n");
	return CL_CLEAN;
    }
    inst = sctx->inst;
    if(inst && inst->filetype)
	return CL_CLEAN; /* Just in case, this shouldn't happen */

    logg("*in prescan_cb with clamav context %p, instance %p, fd %d, type %s)\n", context, inst, fd, type);
    ftype_bits(type, si.filetype);
    si.cbSize = sizeof(si);
    si.flags = 0;
    si.scanPhase = (fd == sctx->entryfd) ? SCAN_PHASE_INITIAL : SCAN_PHASE_PRESCAN;
    si.errorCode = CLAMAPI_SUCCESS;
    si.pThreatType = NULL;
    si.pThreatName = NULL;
    si.pInnerObjectPath = NULL;

    if(si.scanPhase == SCAN_PHASE_PRESCAN) {
	long fpos;
	int rsz;
	perf2 = GetTickCount();
	while(1) {
	    static int tmpn;
	    snprintf(tmpf, sizeof(tmpf), "%s\\%08x.tmp", tmpdir, ++tmpn);
	    tmpf[sizeof(tmpf)-1] = '\0';
	    fdhdl = CreateFile(tmpf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL);
	    if(fdhdl != INVALID_HANDLE_VALUE) {
		logg("*prescan_cb: dumping content to tempfile %s (handle %p)\n", tmpf, fdhdl);
		break;
	    }
	    if((perf = GetLastError()) != ERROR_FILE_EXISTS) {
		logg("!prescan_cb: failed to create tempfile %s - error %u\n", tmpf, perf);
		return CL_CLEAN;
	    }
	}

	fpos = lseek(fd, 0, SEEK_CUR);
	lseek(fd, 0, SEEK_SET);
	while((rsz = read(fd, tmpf, sizeof(tmpf))) > 0) {
	    int wsz = 0;
	    while(wsz != rsz) {
		DWORD rwsz;
		if(!WriteFile(fdhdl, &tmpf[wsz], rsz - wsz, &rwsz, NULL)) {
		    logg("!prescan_cb: failed to write to tempfile %s - error %u\n", GetLastError());
		    lseek(fd, fpos, SEEK_SET);
		    CloseHandle(fdhdl);
		    return CL_CLEAN;
		}
		wsz += rwsz;
	    }
	}
	if(rsz) {
	    logg("!prescan_cb: failed to read from clamav tempfile - errno = %d\n", errno);
	    lseek(fd, fpos, SEEK_SET);
	    CloseHandle(fdhdl);
	    return CL_CLEAN;
	}
	lseek(fd, fpos, SEEK_SET);
	SetFilePointer(fdhdl, 0, NULL, FILE_BEGIN);
	si.object = fdhdl;
	si.objectId = (HANDLE)_get_osfhandle(fd);
	perf2 = GetTickCount() - perf2;
	sctx->copy_times += perf2;
    } else { /* SCAN_PHASE_INITIAL */
	si.object = INVALID_HANDLE_VALUE;
	si.objectId = INVALID_HANDLE_VALUE;
    }
    logg("*prescan_cb (clamav context %p, instance %p) invoking callback %p with context %p\n", context, inst, inst->scancb, inst->scancb_ctx);
    perf = GetTickCount();
    inst->scancb(&si, &act, inst->scancb_ctx);
    perf = GetTickCount() - perf;
    sctx->cb_times += perf;
    logg("*prescan_cb (clamav context %p, instance %p) callback completed with %u in %u + %u ms\n", context, inst, act, perf, perf2);
    switch(act) {
	case CLAM_ACTION_SKIP:
	    logg("*prescan_cb (clamav context %p, instance %p) cb result: SKIP\n", context, inst);
	    return CL_BREAK;
	case CLAM_ACTION_ABORT:
	    logg("*prescan_cb (clamav context %p, instance %p) cb result: ABORT\n", context, inst);
	    return CL_VIRUS;
	case CLAM_ACTION_CONTINUE:
	    logg("*prescan_cb (clamav context %p, instance %p) cb result: CONTINUE\n", context, inst);
	    return CL_CLEAN;
	default:
	    logg("^prescan_cb (clamav context %p, instance %p) cb result: INVALID result %d, assuming continue\n", context, inst, act);
	    return CL_CLEAN;
    }
}
Beispiel #4
0
static int
pduread(int fd, char *buf, int len, int part, int timeout)
{
    int			socketipc = __pmSocketIPC(fd);
    int			status = 0;
    int			have = 0;
    int			onetrip = 1;
    struct timeval	dead_hand;
    struct timeval	now;

    if (timeout == -2 /*TIMEOUT_ASYNC*/)
	return -EOPNOTSUPP;

    /*
     * Handle short reads that may split a PDU ...
     *
     * The original logic here assumed that recv() would only split a
     * PDU at a word (__pmPDU) boundary ... with the introduction of
     * secure connections, SSL and possibly compression all lurking
     * below the socket covers, this is no longer a safe assumption.
     *
     * So, we keep nibbling at the input stream until we have all that
     * we have requested, or we timeout, or error.
     */
    while (len) {
	struct timeval	wait;

#if defined(IS_MINGW)	/* cannot select on a pipe on Win32 - yay! */
	if (!__pmSocketIPC(fd)) {
	    COMMTIMEOUTS cwait = { 0 };

	    if (timeout != TIMEOUT_NEVER)
		cwait.ReadTotalTimeoutConstant = timeout * 1000.0;
	    else
		cwait.ReadTotalTimeoutConstant = def_timeout * 1000.0;
	    SetCommTimeouts((HANDLE)_get_osfhandle(fd), &cwait);
	}
	else
#endif

	/*
	 * either never timeout (i.e. block forever), or timeout
	 */
	if (timeout != TIMEOUT_NEVER) {
	    if (timeout > 0) {
		wait.tv_sec = timeout;
		wait.tv_usec = 0;
	    }
	    else
		wait = def_wait;
	    if (onetrip) {
		/*
		 * Need all parts of the PDU to be received by dead_hand
		 * This enforces a low overall timeout for the whole PDU
		 * (as opposed to just a timeout for individual calls to
		 * recv).  A more invasive alternative (better) approach
		 * would see all I/O performed in the main event loop,
		 * and I/O routines transformed to continuation-passing
		 * style.
		 */
		gettimeofday(&dead_hand, NULL);
		dead_hand.tv_sec += wait.tv_sec;
		dead_hand.tv_usec += wait.tv_usec;
		while (dead_hand.tv_usec >= 1000000) {
		    dead_hand.tv_usec -= 1000000;
		    dead_hand.tv_sec++;
		}
		onetrip = 0;
	    }

	    status = __pmSocketReady(fd, &wait);
	    if (status > 0) {
		gettimeofday(&now, NULL);
		if (now.tv_sec > dead_hand.tv_sec ||
		    (now.tv_sec == dead_hand.tv_sec &&
		     now.tv_usec > dead_hand.tv_usec))
		    status = 0;
	    }
	    if (status == 0) {
		if (__pmGetInternalState() != PM_STATE_APPL) {
		    /* special for PMCD and friends 
		     * Note, on Linux select would return 'time remaining'
		     * in timeout value, so report the expected timeout
		     */
		    int tosec, tomsec;

		    if ( timeout != TIMEOUT_NEVER && timeout > 0 ) {
			tosec = (int)timeout;
			tomsec = 0;
		    } else {
			tosec = (int)def_wait.tv_sec;
			tomsec = 1000*(int)def_wait.tv_usec;
		    }

		    __pmNotifyErr(LOG_WARNING, 
				  "pduread: timeout (after %d.%03d "
				  "sec) while attempting to read %d "
				  "bytes out of %d in %s on fd=%d",
				  tosec, tomsec, len - have, len, 
				  part == HEADER ? "HDR" : "BODY", fd);
		}
		return PM_ERR_TIMEOUT;
	    }
	    else if (status < 0) {
		char	errmsg[PM_MAXERRMSGLEN];
		__pmNotifyErr(LOG_ERR, "pduread: select() on fd=%d: %s",
			fd, netstrerror_r(errmsg, sizeof(errmsg)));
		setoserror(neterror());
		return status;
	    }
	}
	if (socketipc) {
	    status = __pmRecv(fd, buf, len, 0);
	    setoserror(neterror());
	} else {
	    status = read(fd, buf, len);
	}
	__pmOverrideLastFd(fd);
	if (status < 0)
	    /* error */
	    return status;
	else if (status == 0)
	    /* return what we have, or nothing */
	    break;

	have += status;
	buf += status;
	len -= status;
#ifdef PCP_DEBUG
	if ((pmDebug & DBG_TRACE_PDU) && (pmDebug & DBG_TRACE_DESPERATE)) {
	    fprintf(stderr, "pduread(%d, ...): have %d, last read %d, still need %d\n",
		fd, have, status, len);
	}
#endif
    }

    return have;
}
Beispiel #5
0
void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
{
    HANDLE fm, h;
    
    void * map = MAP_FAILED;
    
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4293)
#endif

    const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ? 
                    (DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
    const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
                    (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
    const DWORD protect = __map_mmap_prot_page(prot);
    const DWORD desiredAccess = __map_mmap_prot_file(prot);

    const off_t maxSize = off + (off_t)len;

    const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) ? 
                    (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL);
    const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
                    (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL);

#ifdef _MSC_VER
#pragma warning(pop)
#endif

    errno = 0;
    
    if (len == 0 
        /* Unsupported flag combinations */
        || (flags & MAP_FIXED) != 0
        /* Usupported protection combinations */
        || prot == PROT_EXEC)
    {
        errno = EINVAL;
        return MAP_FAILED;
    }
    
    h = ((flags & MAP_ANONYMOUS) == 0) ? 
                    (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE;

    if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE)
    {
        errno = EBADF;
        return MAP_FAILED;
    }

    fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL);

    if (fm == NULL)
    {
        errno = __map_mman_error(GetLastError(), EPERM);
        return MAP_FAILED;
    }
  
    map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len);

    CloseHandle(fm);
  
    if (map == NULL)
    {
        errno = __map_mman_error(GetLastError(), EPERM);
        return MAP_FAILED;
    }

    return map;
}
/* Fork and exec the PGMNAME, see exechelp.h for details.  */
gpg_error_t
gnupg_spawn_process (const char *pgmname, const char *argv[],
                     gpg_err_source_t errsource,
                     void (*preexec)(void), unsigned int flags,
                     estream_t infp,
                     estream_t *r_outfp,
                     estream_t *r_errfp,
                     pid_t *pid)
{
  gpg_error_t err;
  SECURITY_ATTRIBUTES sec_attr;
  PROCESS_INFORMATION pi =
    {
      NULL,      /* Returns process handle.  */
      0,         /* Returns primary thread handle.  */
      0,         /* Returns pid.  */
      0          /* Returns tid.  */
    };
  STARTUPINFO si;
  int cr_flags;
  char *cmdline;
  HANDLE inhandle = INVALID_HANDLE_VALUE;
  HANDLE outpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
  HANDLE errpipe[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
  estream_t outfp = NULL;
  estream_t errfp = NULL;
  HANDLE nullhd[3] = {INVALID_HANDLE_VALUE,
                      INVALID_HANDLE_VALUE,
                      INVALID_HANDLE_VALUE};
  int i;
  es_syshd_t syshd;

  if (r_outfp)
    *r_outfp = NULL;
  if (r_errfp)
    *r_errfp = NULL;
  *pid = (pid_t)(-1); /* Always required.  */

  if (infp)
    {
      es_fflush (infp);
      es_rewind (infp);
      es_syshd (infp, &syshd);
      switch (syshd.type)
        {
        case ES_SYSHD_FD:
          inhandle = (HANDLE)_get_osfhandle (syshd.u.fd);
          break;
        case ES_SYSHD_SOCK:
          inhandle = (HANDLE)_get_osfhandle (syshd.u.sock);
          break;
        case ES_SYSHD_HANDLE:
          inhandle = syshd.u.handle;
          break;
        default:
          inhandle = INVALID_HANDLE_VALUE;
          break;
        }
      if (inhandle == INVALID_HANDLE_VALUE)
        return gpg_err_make (errsource, GPG_ERR_INV_VALUE);
      /* FIXME: In case we can't get a system handle (e.g. due to
         es_fopencookie we should create a piper and a feeder
         thread.  */
    }

  if (r_outfp)
    {
      if (create_inheritable_pipe (outpipe, 1))
        {
          err = gpg_err_make (errsource, GPG_ERR_GENERAL);
          log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
          return err;
        }

      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = outpipe[0];
      outfp = es_sysopen (&syshd, "r");
      if (!outfp)
        {
          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
          log_error (_("error creating a stream for a pipe: %s\n"),
                     gpg_strerror (err));
          CloseHandle (outpipe[0]);
          CloseHandle (outpipe[1]);
          outpipe[0] = outpipe[1] = INVALID_HANDLE_VALUE;
          return err;
        }
    }

  if (r_errfp)
    {
      if (create_inheritable_pipe (errpipe, 1))
        {
          err = gpg_err_make (errsource, GPG_ERR_GENERAL);
          log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
          return err;
        }

      syshd.type = ES_SYSHD_HANDLE;
      syshd.u.handle = errpipe[0];
      errfp = es_sysopen (&syshd, "r");
      if (!errfp)
        {
          err = gpg_err_make (errsource, gpg_err_code_from_syserror ());
          log_error (_("error creating a stream for a pipe: %s\n"),
                     gpg_strerror (err));
          CloseHandle (errpipe[0]);
          CloseHandle (errpipe[1]);
          errpipe[0] = errpipe[1] = INVALID_HANDLE_VALUE;
          if (outfp)
            es_fclose (outfp);
          else if (outpipe[0] != INVALID_HANDLE_VALUE)
            CloseHandle (outpipe[0]);
          if (outpipe[1] != INVALID_HANDLE_VALUE)
            CloseHandle (outpipe[1]);
          return err;
        }
    }

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr );
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;

  /* Build the command line.  */
  err = build_w32_commandline (pgmname, argv, &cmdline);
  if (err)
    return err;

  if (inhandle != INVALID_HANDLE_VALUE)
    nullhd[0] = w32_open_null (0);
  if (outpipe[1] != INVALID_HANDLE_VALUE)
    nullhd[1] = w32_open_null (0);
  if (errpipe[1] != INVALID_HANDLE_VALUE)
    nullhd[2] = w32_open_null (0);

  /* Start the process.  Note that we can't run the PREEXEC function
     because this might change our own environment. */
  (void)preexec;

  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
  si.hStdInput  =   inhandle == INVALID_HANDLE_VALUE? nullhd[0] : inhandle;
  si.hStdOutput = outpipe[1] == INVALID_HANDLE_VALUE? nullhd[1] : outpipe[1];
  si.hStdError  = errpipe[1] == INVALID_HANDLE_VALUE? nullhd[2] : errpipe[1];

  cr_flags = (CREATE_DEFAULT_ERROR_MODE
              | ((flags & 128)? DETACHED_PROCESS : 0)
              | GetPriorityClass (GetCurrentProcess ())
              | CREATE_SUSPENDED);
/*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
  if (!CreateProcess (pgmname,       /* Program to start.  */
                      cmdline,       /* Command line arguments.  */
                      &sec_attr,     /* Process security attributes.  */
                      &sec_attr,     /* Thread security attributes.  */
                      TRUE,          /* Inherit handles.  */
                      cr_flags,      /* Creation flags.  */
                      NULL,          /* Environment.  */
                      NULL,          /* Use current drive/directory.  */
                      &si,           /* Startup information. */
                      &pi            /* Returns process information.  */
                      ))
    {
      log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
      xfree (cmdline);
      if (outfp)
        es_fclose (outfp);
      else if (outpipe[0] != INVALID_HANDLE_VALUE)
        CloseHandle (outpipe[0]);
      if (outpipe[1] != INVALID_HANDLE_VALUE)
        CloseHandle (outpipe[1]);
      if (errfp)
        es_fclose (errfp);
      else if (errpipe[0] != INVALID_HANDLE_VALUE)
        CloseHandle (errpipe[0]);
      if (errpipe[1] != INVALID_HANDLE_VALUE)
        CloseHandle (errpipe[1]);
      return gpg_err_make (errsource, GPG_ERR_GENERAL);
    }
  xfree (cmdline);
  cmdline = NULL;

  /* Close the inherited handles to /dev/null.  */
  for (i=0; i < DIM (nullhd); i++)
    if (nullhd[i] != INVALID_HANDLE_VALUE)
      CloseHandle (nullhd[i]);

  /* Close the inherited ends of the pipes.  */
  if (outpipe[1] != INVALID_HANDLE_VALUE)
    CloseHandle (outpipe[1]);
  if (errpipe[1] != INVALID_HANDLE_VALUE)
    CloseHandle (errpipe[1]);

  /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
  /*            " dwProcessID=%d dwThreadId=%d\n", */
  /*            pi.hProcess, pi.hThread, */
  /*            (int) pi.dwProcessId, (int) pi.dwThreadId); */
  /* log_debug ("                     outfp=%p errfp=%p\n", outfp, errfp); */

  /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
     invalid argument error if we pass it the correct processID.  As a
     workaround we use -1 (ASFW_ANY).  */
  if ( (flags & 64) )
    gnupg_allow_set_foregound_window ((pid_t)(-1)/*pi.dwProcessId*/);

  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread);

  if (r_outfp)
    *r_outfp = outfp;
  if (r_errfp)
    *r_errfp = errfp;

  *pid = handle_to_pid (pi.hProcess);
  return 0;

}
Beispiel #7
0
gboolean
gimp_plug_in_open (GimpPlugIn         *plug_in,
                   GimpPlugInCallMode  call_mode,
                   gboolean            synchronous)
{
  gint          my_read[2];
  gint          my_write[2];
  gchar       **envp;
  const gchar  *args[9];
  gchar       **argv;
  gint          argc;
  gchar        *interp, *interp_arg;
  gchar        *read_fd, *write_fd;
  const gchar  *mode;
  gchar        *stm;
  GError       *error = NULL;
  gboolean      debug;
  guint         debug_flag;
  guint         spawn_flags;

  g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), FALSE);
  g_return_val_if_fail (plug_in->call_mode == GIMP_PLUG_IN_CALL_NONE, FALSE);

  /* Open two pipes. (Bidirectional communication).
   */
  if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
    {
      gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
                    "Unable to run plug-in \"%s\"\n(%s)\n\npipe() failed: %s",
                    gimp_object_get_name (plug_in),
                    gimp_filename_to_utf8 (plug_in->prog),
                    g_strerror (errno));
      return FALSE;
    }

#if defined(G_WITH_CYGWIN)
  /* Set to binary mode */
  setmode (my_read[0], _O_BINARY);
  setmode (my_write[0], _O_BINARY);
  setmode (my_read[1], _O_BINARY);
  setmode (my_write[1], _O_BINARY);
#endif

#ifdef G_OS_WIN32
  /* Prevent the plug-in from inheriting our ends of the pipes */
  SetHandleInformation ((HANDLE) _get_osfhandle (my_read[0]), HANDLE_FLAG_INHERIT, 0);
  SetHandleInformation ((HANDLE) _get_osfhandle (my_write[1]), HANDLE_FLAG_INHERIT, 0);
#endif

  plug_in->my_read   = g_io_channel_unix_new (my_read[0]);
  plug_in->my_write  = g_io_channel_unix_new (my_write[1]);
  plug_in->his_read  = g_io_channel_unix_new (my_write[0]);
  plug_in->his_write = g_io_channel_unix_new (my_read[1]);

  g_io_channel_set_encoding (plug_in->my_read, NULL, NULL);
  g_io_channel_set_encoding (plug_in->my_write, NULL, NULL);
  g_io_channel_set_encoding (plug_in->his_read, NULL, NULL);
  g_io_channel_set_encoding (plug_in->his_write, NULL, NULL);

  g_io_channel_set_buffered (plug_in->my_read, FALSE);
  g_io_channel_set_buffered (plug_in->my_write, FALSE);
  g_io_channel_set_buffered (plug_in->his_read, FALSE);
  g_io_channel_set_buffered (plug_in->his_write, FALSE);

  g_io_channel_set_close_on_unref (plug_in->my_read, TRUE);
  g_io_channel_set_close_on_unref (plug_in->my_write, TRUE);
  g_io_channel_set_close_on_unref (plug_in->his_read, TRUE);
  g_io_channel_set_close_on_unref (plug_in->his_write, TRUE);

  /* Remember the file descriptors for the pipes.
   */
  read_fd  = g_strdup_printf ("%d",
                              g_io_channel_unix_get_fd (plug_in->his_read));
  write_fd = g_strdup_printf ("%d",
                              g_io_channel_unix_get_fd (plug_in->his_write));

  switch (call_mode)
    {
    case GIMP_PLUG_IN_CALL_QUERY:
      mode = "-query";
      debug_flag = GIMP_DEBUG_WRAP_QUERY;
      break;

    case GIMP_PLUG_IN_CALL_INIT:
      mode = "-init";
      debug_flag = GIMP_DEBUG_WRAP_INIT;
      break;

    case GIMP_PLUG_IN_CALL_RUN:
      mode = "-run";
      debug_flag = GIMP_DEBUG_WRAP_RUN;
      break;

    default:
      g_assert_not_reached ();
    }

  stm = g_strdup_printf ("%d", plug_in->manager->gimp->stack_trace_mode);

  interp = gimp_interpreter_db_resolve (plug_in->manager->interpreter_db,
                                        plug_in->prog, &interp_arg);

  argc = 0;

  if (interp)
    args[argc++] = interp;

  if (interp_arg)
    args[argc++] = interp_arg;

  args[argc++] = plug_in->prog;
  args[argc++] = "-gimp";
  args[argc++] = read_fd;
  args[argc++] = write_fd;
  args[argc++] = mode;
  args[argc++] = stm;
  args[argc++] = NULL;

  argv = (gchar **) args;
  envp = gimp_environ_table_get_envp (plug_in->manager->environ_table);
  spawn_flags = (G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
                 G_SPAWN_DO_NOT_REAP_CHILD      |
                 G_SPAWN_CHILD_INHERITS_STDIN);

  debug = FALSE;

  if (plug_in->manager->debug)
    {
      gchar **debug_argv = gimp_plug_in_debug_argv (plug_in->manager->debug,
                                                    plug_in->prog,
                                                    debug_flag, args);

      if (debug_argv)
        {
          debug = TRUE;
          argv = debug_argv;
          spawn_flags |= G_SPAWN_SEARCH_PATH;
        }
    }

  /* Fork another process. We'll remember the process id so that we
   * can later use it to kill the filter if necessary.
   */
  if (! g_spawn_async (NULL, argv, envp, spawn_flags,
                       gimp_plug_in_prep_for_exec, plug_in,
                       &plug_in->pid,
                       &error))
    {
      gimp_message (plug_in->manager->gimp, NULL, GIMP_MESSAGE_ERROR,
                    "Unable to run plug-in \"%s\"\n(%s)\n\n%s",
                    gimp_object_get_name (plug_in),
                    gimp_filename_to_utf8 (plug_in->prog),
                    error->message);
      g_error_free (error);
      goto cleanup;
    }

  g_io_channel_unref (plug_in->his_read);
  plug_in->his_read = NULL;

  g_io_channel_unref (plug_in->his_write);
  plug_in->his_write = NULL;

  if (! synchronous)
    {
      GSource *source;

      source = g_io_create_watch (plug_in->my_read,
                                  G_IO_IN  | G_IO_PRI | G_IO_ERR | G_IO_HUP);

      g_source_set_callback (source,
                             (GSourceFunc) gimp_plug_in_recv_message, plug_in,
                             NULL);

      g_source_set_can_recurse (source, TRUE);

      plug_in->input_id = g_source_attach (source, NULL);
      g_source_unref (source);
    }

  plug_in->open      = TRUE;
  plug_in->call_mode = call_mode;

  gimp_plug_in_manager_add_open_plug_in (plug_in->manager, plug_in);

 cleanup:

  if (debug)
    g_free (argv);

  g_free (read_fd);
  g_free (write_fd);
  g_free (stm);
  g_free (interp);
  g_free (interp_arg);

  return plug_in->open;
}
Beispiel #8
0
void open_term()
{
    TERM_FH = fopen("CONOUT$", "w+");
    con = (HANDLE)_get_osfhandle(fileno(TERM_FH));
}
Beispiel #9
0
int uv_is_tty(uv_file file) {
  DWORD result;
  int r = GetConsoleMode((HANDLE)_get_osfhandle(file), &result);
  return r ? 1 : 0;
}
Beispiel #10
0
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
	HANDLE fh = (HANDLE)_get_osfhandle(fd);
	DWORD page_size = get_page_size();
	DWORD fmap_prot = 0;
	DWORD view_prot = 0;
	DWORD off_low = 0;
	DWORD off_hi = 0;
	git_off_t page_start;
	git_off_t page_offset;

	assert((out != NULL) && (len > 0));

	if ((out == NULL) || (len == 0)) {
		errno = EINVAL;
		return git__throw(GIT_ERROR, "Failed to mmap. No map or zero length");
	}

	out->data = NULL;
	out->len = 0;
	out->fmh = NULL;

	if (fh == INVALID_HANDLE_VALUE) {
		errno = EBADF;
		return git__throw(GIT_ERROR, "Failed to mmap. Invalid handle value");
	}

	if (prot & GIT_PROT_WRITE)
		fmap_prot |= PAGE_READWRITE;
	else if (prot & GIT_PROT_READ)
		fmap_prot |= PAGE_READONLY;
	else {
		errno = EINVAL;
		return git__throw(GIT_ERROR, "Failed to mmap. Invalid protection parameters");
	}

	if (prot & GIT_PROT_WRITE)
		view_prot |= FILE_MAP_WRITE;
	if (prot & GIT_PROT_READ)
		view_prot |= FILE_MAP_READ;

	if (flags & GIT_MAP_FIXED) {
		errno = EINVAL;
		return git__throw(GIT_ERROR, "Failed to mmap. FIXED not set");
	}

	page_start = (offset / page_size) * page_size;
	page_offset = offset - page_start;

	if (page_offset != 0) { /* offset must be multiple of page size */
		errno = EINVAL;
		return git__throw(GIT_ERROR, "Failed to mmap. Offset must be multiple of page size");
	}

	out->fmh = CreateFileMapping(fh, NULL, fmap_prot, 0, 0, NULL);
	if (!out->fmh || out->fmh == INVALID_HANDLE_VALUE) {
		/* errno = ? */
		out->fmh = NULL;
		return git__throw(GIT_ERROR, "Failed to mmap. Invalid handle value");
	}

	assert(sizeof(git_off_t) == 8);
	off_low = (DWORD)(page_start);
	off_hi = (DWORD)(page_start >> 32);
	out->data = MapViewOfFile(out->fmh, view_prot, off_hi, off_low, len);
	if (!out->data) {
		/* errno = ? */
		CloseHandle(out->fmh);
		out->fmh = NULL;
		return git__throw(GIT_ERROR, "Failed to mmap. No data written");
	}
	out->len = len;

	return GIT_SUCCESS;
}
Beispiel #11
0
static int run_process(zzuf_child_t *child, zzuf_opts_t *opts, int pipes[][2])
{
#if defined HAVE_FORK
#   if defined __APPLE__
#       define EXTRAINFO ""
#       define PRELOAD "DYLD_INSERT_LIBRARIES"
    /* Only enforce flat namespace in preload mode */
    if (opts->opmode == OPMODE_PRELOAD)
        setenv("DYLD_FORCE_FLAT_NAMESPACE", "1", 1);
#   elif defined __osf__
#       define EXTRAINFO ":DEFAULT"
#       define PRELOAD "_RLD_LIST"
#   elif defined __sun && defined __i386
#       define EXTRAINFO ""
#       define PRELOAD "LD_PRELOAD_32"
#   else
#       define EXTRAINFO ""
#       define PRELOAD "LD_PRELOAD"
#   endif

    /* Fork and launch child */
    int pid = fork();
    if (pid < 0)
    {
        perror("fork");
        return -1;
    }

    if (pid != 0)
    {
        /* We are the parent. Close the pipe fds used for writing, since
         * we will only be reading. */
        for (int j = 3; j--; )
            close(pipes[j][1]);

        return pid;
    }

    /* We are the child. Close the pipe fds used for reading, since we
     * will only be writing. Also, if the fd number does not match what
     * we expect (for whatever reason), call dup2() and close the fd with
     * the wrong number. We loop in reverse order so that files[0] (the
     * debug fd) is done last, because it is the most important to us. */
    static int const fds[] = { DEBUG_FILENO, STDERR_FILENO, STDOUT_FILENO };
    for (int j = 3; j--; )
    {
        close(pipes[j][0]);
        if (pipes[j][1] != fds[j])
        {
            dup2(pipes[j][1], fds[j]);
            close(pipes[j][1]);
            pipes[j][1] = fds[j];
        }
    }
#endif

#if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_MEM
    if (opts->maxmem >= 0)
    {
        struct rlimit rlim;
        rlim.rlim_cur = opts->maxmem * 1048576;
        rlim.rlim_max = opts->maxmem * 1048576;
        setrlimit(ZZUF_RLIMIT_MEM, &rlim);
    }
#endif

#if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_CPU
    if (opts->maxcpu >= 0)
    {
        struct rlimit rlim;
        rlim.rlim_cur = opts->maxcpu;
        rlim.rlim_max = opts->maxcpu + 5;
        setrlimit(ZZUF_RLIMIT_CPU, &rlim);
    }
#endif

    /* Set environment variables */
    char buf[64];
#if defined _WIN32
    sprintf(buf, "%i", _get_osfhandle(pipes[0][1]));
#else
    sprintf(buf, "%i", pipes[0][1]);
#endif
    setenv("ZZUF_DEBUGFD", buf, 1);
    sprintf(buf, "%i", opts->seed);
    setenv("ZZUF_SEED", buf, 1);
    sprintf(buf, "%g", opts->minratio);
    setenv("ZZUF_MINRATIO", buf, 1);
    sprintf(buf, "%g", opts->maxratio);
    setenv("ZZUF_MAXRATIO", buf, 1);

#if defined HAVE_FORK
    /* Make sure there is space for everything we might do. */
    int len = strlen(opts->oldargv[0]);
    char *libpath =
               malloc(len + strlen(LIBDIR "/" LT_OBJDIR SONAME EXTRAINFO) + 1);
    strcpy(libpath, opts->oldargv[0]);

    /* If the binary name contains a '/', we look for a libzzuf in the
     * same directory. Otherwise, we only look into the system directory
     * to avoid shared library attacks. Write the result in libpath. */
    char *tmp = strrchr(libpath, '/');
    if (tmp)
    {
        strcpy(tmp + 1, LT_OBJDIR SONAME);
        if (access(libpath, R_OK) < 0)
            strcpy(libpath, LIBDIR "/" SONAME);
    }
    else
        strcpy(libpath, LIBDIR "/" SONAME);

    /* OSF1 only */
    strcat(libpath, EXTRAINFO);

    /* Do not clobber previous LD_PRELOAD values */
    tmp = getenv(PRELOAD);
    if (tmp && *tmp)
    {
        char *bigbuf = malloc(strlen(tmp) + strlen(libpath) + 2);
        sprintf(bigbuf, "%s:%s", tmp, libpath);
        free(libpath);
        libpath = bigbuf;
    }

    /* Only preload the library in preload mode */
    if (opts->opmode == OPMODE_PRELOAD)
        setenv(PRELOAD, libpath, 1);
    free(libpath);

    if (execvp(child->newargv[0], child->newargv))
    {
        perror(child->newargv[0]);
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
    /* no return */
    return 0;

#elif HAVE_WINDOWS_H
    /* Inherit standard handles */
    STARTUPINFO sinfo;
    memset(&sinfo, 0, sizeof(sinfo));
    sinfo.cb = sizeof(sinfo);
    sinfo.hStdInput = INVALID_HANDLE_VALUE;
    sinfo.hStdOutput = (HANDLE)_get_osfhandle(pipes[2][1]);
    sinfo.hStdError = (HANDLE)_get_osfhandle(pipes[1][1]);
    sinfo.dwFlags = STARTF_USESTDHANDLES;

    /* Build the commandline */
    int len = 0;
    for (int i = 0; child->newargv[i]; ++i)
        len += (int)strlen(child->newargv[i]) + 1;
    char *cmdline = malloc(len);

    len = 0;
    for (int i = 0; child->newargv[i]; ++i)
    {
        strcpy(cmdline + len, child->newargv[i]);
        len += (int)strlen(child->newargv[i]) + 1;
        cmdline[len - 1] = ' ';
    }
    cmdline[len - 1] = '\0';

    /* Create the process in suspended state */
    PROCESS_INFORMATION pinfo;
    int ret = CreateProcess(child->newargv[0], cmdline, NULL, NULL, TRUE,
                            CREATE_SUSPENDED, NULL, NULL, &sinfo, &pinfo);
    free(cmdline);

    child->process_handle = pinfo.hProcess;
    child->pid            = pinfo.dwProcessId;

    if (!ret)
    {
        LPTSTR tmp;
        DWORD err = GetLastError();
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                      FORMAT_MESSAGE_FROM_SYSTEM     |
                      FORMAT_MESSAGE_IGNORE_INSERTS,
                      NULL, err, 0, (LPTSTR)&tmp, 0, NULL);
        fprintf(stderr, "error launching `%s': %s\n", child->newargv[0], tmp);
        LocalFree(tmp);
        return -1;
    }

    /* Insert the replacement code */
    ret = dll_inject(&pinfo, SONAME);
    if (ret < 0)
    {
        TerminateProcess(pinfo.hProcess, -1);
        return -1;
    }

    /* Insert your breakpoint here to have a chance to attach a debugger
     * to libzzuf.dll */
    ret = ResumeThread(pinfo.hThread);
    if (ret == -1)
    {
        TerminateProcess(pinfo.hProcess, -1);
        return -1;
    }

    return (long int)pinfo.hProcess;
#endif
}
Beispiel #12
0
int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) {
  HANDLE handle = INVALID_HANDLE_VALUE;
  DWORD original_console_mode = 0;
  CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info;

  handle = (HANDLE) _get_osfhandle(fd);
  if (handle == INVALID_HANDLE_VALUE) {
    uv__set_artificial_error(loop, UV_EBADF);
    return -1;
  }

  if (readable) {
     /* Try to obtain the original console mode fromt he input handle. */
    if (!GetConsoleMode(handle, &original_console_mode)) {
      uv__set_sys_error(loop, GetLastError());
      return -1;
    }

  } else {
    /* Obtain the screen buffer info with the output handle. */
    if (!GetConsoleScreenBufferInfo(handle, &screen_buffer_info)) {
      uv__set_sys_error(loop, GetLastError());
      return -1;
    }

    /* Obtain the the tty_output_lock because the virtual window state is */
    /* shared between all uv_tty_t handles. */
    EnterCriticalSection(&uv_tty_output_lock);

    /* Store the global tty output handle. This handle is used by TTY read */
    /* streams to update the virtual window when a CONSOLE_BUFFER_SIZE_EVENT */
    /* is received. */
    uv_tty_output_handle = handle;

    uv_tty_update_virtual_window(&screen_buffer_info);

    LeaveCriticalSection(&uv_tty_output_lock);
  }


  uv_stream_init(loop, (uv_stream_t*) tty, UV_TTY);
  uv_connection_init((uv_stream_t*) tty);

  tty->handle = handle;
  tty->reqs_pending = 0;
  tty->flags |= UV_HANDLE_BOUND;

  if (readable) {
    /* Initialize TTY input specific fields. */
    tty->original_console_mode = original_console_mode;
    tty->flags |= UV_HANDLE_TTY_READABLE | UV_HANDLE_READABLE;
    tty->read_line_handle = NULL;
    tty->read_line_buffer = uv_null_buf_;
    tty->read_raw_wait = NULL;

    /* Init keycode-to-vt100 mapper state. */
    tty->last_key_len = 0;
    tty->last_key_offset = 0;
    tty->last_utf16_high_surrogate = 0;
    memset(&tty->last_input_record, 0, sizeof tty->last_input_record);
  } else {
    /* TTY output specific fields. */
    tty->flags |= UV_HANDLE_WRITABLE;

    /* Init utf8-to-utf16 conversion state. */
    tty->utf8_bytes_left = 0;
    tty->utf8_codepoint = 0;

    /* Initialize eol conversion state */
    tty->previous_eol = 0;

    /* Init ANSI parser state. */
    tty->ansi_parser_state = ANSI_NORMAL;
  }

  return 0;
}
Beispiel #13
0
int
fsync(int fd)
{
    return FlushFileBuffers((HANDLE)_get_osfhandle(fd)) ? 0 : -1;
}
Beispiel #14
0
static unsigned int __stdcall
ipc_thread_1(void *in_params)
{
    int t1, t2, t3, retval = -1;
    int p2c[2] =
    {-1, -1};
    int c2p[2] =
    {-1, -1};
    HANDLE hProcess = NULL, thread = NULL;
    pid_t pid = -1;
    struct thread_params thread_params;
    int x, tmp_s, fd = -1;
    char *str;
#if HAVE_PUTENV
    char *env_str = NULL;
#endif
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    long F;
    int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1;
    char *prog = NULL, *buf1 = NULL;
    struct sockaddr_in CS_ipc, PS_ipc;

    struct ipc_params *params = (struct ipc_params *) in_params;
    int type = params->type;
    int crfd = params->crfd;
    int cwfd = params->cwfd;
    char **args = params->args;
    struct sockaddr_in PS = params->PS;


    buf1 = xcalloc(1, 8192);
    strcpy(buf1, params->prog);
    prog = strtok(buf1, w_space);

    if ((str = strrchr(prog, '/')))
	prog = ++str;
    if ((str = strrchr(prog, '\\')))
	prog = ++str;

    prog = xstrdup(prog);

    if (type == IPC_TCP_SOCKET) {
	debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
	if ((fd = accept(crfd, NULL, NULL)) < 0) {
	    debug(54, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
	    goto cleanup;
	}
	debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
	comm_close(crfd);
	snprintf(buf1, 8191, "%s CHILD socket", prog);
	fd_open(fd, FD_SOCKET, buf1);
	fd_table[fd].flags.ipc = 1;
	cwfd = crfd = fd;
    } else if (type == IPC_UDP_SOCKET) {
	if (comm_connect_addr(crfd, &PS) == COMM_ERROR)
	    goto cleanup;
    }
    x = send(cwfd, hello_string, strlen(hello_string) + 1, 0);

    if (x < 0) {
	debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
	debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n");
	goto cleanup;
    }
#if HAVE_PUTENV
    env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
    snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
    putenv(env_str);
#endif
    memset(buf1, '\0', sizeof(buf1));
    x = recv(crfd, buf1, 8191, 0);

    if (x < 0) {
	debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
	debug(54, 0) ("--> read: %s\n", xstrerror());
	goto cleanup;
    } else if (strcmp(buf1, ok_string)) {
	debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n");
	debug(54, 0) ("--> read returned %d\n", x);
	debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
	goto cleanup;
    }
    /* assign file descriptors to child process */
    if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
	debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
	ipcSend(cwfd, err_string, strlen(err_string));
	goto cleanup;
    }
    if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) {
	debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror());
	ipcSend(cwfd, err_string, strlen(err_string));
	goto cleanup;
    }
    if (type == IPC_UDP_SOCKET) {
	snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", prog, -1L);
	crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1);

	if (crfd_ipc < 0) {
	    debug(54, 0) ("ipcCreate: CHILD: Failed to create child FD for %s.\n",
		prog);
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", prog, -1L);
	prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1);
	if (pwfd_ipc < 0) {
	    debug(54, 0) ("ipcCreate: CHILD: Failed to create server FD for %s.\n",
		prog);
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	tmp_s = sizeof(PS_ipc);
	memset(&PS_ipc, '\0', tmp_s);
	if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) {
	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
	    pwfd_ipc, inet_ntoa(PS_ipc.sin_addr), ntohs(PS_ipc.sin_port));
	tmp_s = sizeof(CS_ipc);
	memset(&CS_ipc, '\0', tmp_s);
	if (getsockname(crfd_ipc, (struct sockaddr *) &CS_ipc, &tmp_s) < 0) {
	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
	    crfd_ipc, inet_ntoa(CS_ipc.sin_addr), ntohs(CS_ipc.sin_port));

	if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) {
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	fd = crfd;

	if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) {
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
    }				/* IPC_UDP_SOCKET */
    t1 = dup(0);
    t2 = dup(1);
    t3 = dup(2);
    dup2(c2p[0], 0);
    dup2(p2c[1], 1);
    dup2(fileno(debug_log), 2);
    close(c2p[0]);
    close(p2c[1]);

    commUnsetNonBlocking(fd);

    memset(&si, 0, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.hStdInput = (HANDLE) _get_osfhandle(0);
    si.hStdOutput = (HANDLE) _get_osfhandle(1);
    si.hStdError = (HANDLE) _get_osfhandle(2);
    si.dwFlags = STARTF_USESTDHANDLES;

    /* Make sure all other valid handles are not inerithable */
    for (x = 3; x < Squid_MaxFD; x++) {
	if ((F = _get_osfhandle(x)) == -1)
	    continue;
	SetHandleInformation((HANDLE) F, HANDLE_FLAG_INHERIT, 0);
    }

    *buf1 = '\0';
    strcpy(buf1 + 4096, params->prog);
    str = strtok(buf1 + 4096, w_space);

    do {
	strcat(buf1, str);
	strcat(buf1, " ");
    } while ((str = strtok(NULL, w_space)));

    x = 1;

    while (args[x]) {
	strcat(buf1, args[x++]);
	strcat(buf1, " ");
    }

    if (CreateProcess(buf1 + 4096, buf1, NULL, NULL, TRUE, CREATE_NO_WINDOW,
	    NULL, NULL, &si, &pi)) {
	pid = pi.dwProcessId;
	hProcess = pi.hProcess;
    } else {
	pid = -1;
	WIN32_maperror(GetLastError());
	x = errno;
    }

    dup2(t1, 0);
    dup2(t2, 1);
    dup2(t3, 2);
    close(t1);
    close(t2);
    close(t3);

    if (pid == -1) {
	errno = x;
	debug(54, 0) ("ipcCreate: CHILD: %s: %s\n", params->prog, xstrerror());
	ipcSend(cwfd, err_string, strlen(err_string));
	goto cleanup;
    }
    if (type == IPC_UDP_SOCKET) {
	WSAPROTOCOL_INFO wpi;

	memset(&wpi, 0, sizeof(wpi));
	if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc, pid, &wpi)) {
	    debug(54, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n",
		xstrerror());
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	x = write(c2p[1], (const char *) &wpi, sizeof(wpi));
	if (x < sizeof(wpi)) {
	    debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
		xstrerror());
	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
		prog);
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	x = read(p2c[0], buf1, 8192);
	if (x < 0) {
	    debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
		xstrerror());
	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
		prog);
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	} else if (strncmp(buf1, ok_string, strlen(ok_string))) {
	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
		prog);
	    debug(54, 0) ("--> read returned %d\n", x);
	    buf1[x] = '\0';
	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	x = write(c2p[1], (const char *) &PS_ipc, sizeof(PS_ipc));
	if (x < sizeof(PS_ipc)) {
	    debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1],
		xstrerror());
	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
		prog);
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	x = read(p2c[0], buf1, 8192);
	if (x < 0) {
	    debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0],
		xstrerror());
	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
		prog);
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	} else if (strncmp(buf1, ok_string, strlen(ok_string))) {
	    debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n",
		prog);
	    debug(54, 0) ("--> read returned %d\n", x);
	    buf1[x] = '\0';
	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1));
	    ipcSend(cwfd, err_string, strlen(err_string));
	    goto cleanup;
	}
	x = send(pwfd_ipc, ok_string, strlen(ok_string), 0);
	x = recv(prfd_ipc, buf1 + 200, 8191 - 200, 0);
	assert((size_t) x == strlen(ok_string)
	    && !strncmp(ok_string, buf1 + 200, strlen(ok_string)));
    }				/* IPC_UDP_SOCKET */
    snprintf(buf1, 8191, "%s(%ld) CHILD socket", prog, (long int) pid);
    fd_note(fd, buf1);

    if (prfd_ipc != -1) {
	snprintf(buf1, 8191, "%s(%ld) <-> ipc CHILD socket", prog, (long int) pid);
	fd_note(crfd_ipc, buf1);
	snprintf(buf1, 8191, "%s(%ld) <-> ipc PARENT socket", prog, (long int) pid);
	fd_note(prfd_ipc, buf1);
    }
    /* else {                       IPC_TCP_SOCKET */
    /*     commSetNoLinger(fd); */
    /*  } */
    thread_params.prog = prog;
    thread_params.send_fd = cwfd;
    thread_params.pid = pid;

    if ((thread_params.type = type) == IPC_TCP_SOCKET)
	thread_params.rfd = p2c[0];
    else
	thread_params.rfd = prfd_ipc;

    thread =
	(HANDLE) _beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL);

    if (!thread) {
	debug(54, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror());
	ipcSend(cwfd, err_string, strlen(err_string));
	goto cleanup;
    }
    snprintf(buf1, 8191, "%ld\n", (long int) pid);

    if (-1 == ipcSend(cwfd, buf1, strlen(buf1)))
	goto cleanup;

    debug(54, 2) ("ipc(%s,%ld): started successfully\n", prog, (long int) pid);

    /* cycle */
    for (;;) {
	x = recv(crfd, buf1, 8192, 0);
	if (x <= 0) {
	    debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n",
		prog, pid, x);
	    break;
	}
	buf1[x] = '\0';
	if (type == IPC_UDP_SOCKET && !strcmp(buf1, shutdown_string)) {
	    debug(54, 3)
		("ipc(%s,%d): request for shutdown received from parent. Exiting...\n",
		prog, pid);
	    TerminateProcess(hProcess, 0);
	    break;
	}
	debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", prog, pid,
	    rfc1738_escape_unescaped(buf1));
	if (type == IPC_TCP_SOCKET)
	    x = write(c2p[1], buf1, x);
	else
	    x = send(pwfd_ipc, buf1, x, 0);
	if (x <= 0) {
	    debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n",
		prog, pid, x, prog);
	    break;
	}
    }

    retval = 0;

  cleanup:
    if (c2p[1] != -1)
	close(c2p[1]);

    if (fd_table[crfd].flags.open)
	ipcCloseAllFD(-1, -1, crfd, cwfd);

    if (prfd_ipc != -1) {
	send(crfd_ipc, shutdown_string, strlen(shutdown_string), 0);
	shutdown(crfd_ipc, SD_BOTH);
	shutdown(prfd_ipc, SD_BOTH);
    }
    ipcCloseAllFD(prfd_ipc, pwfd_ipc, crfd_ipc, cwfd_ipc);

    if (hProcess && WAIT_OBJECT_0 !=
	WaitForSingleObject(hProcess, type == IPC_UDP_SOCKET ? 12000 : 5000)) {

	getCurrentTime();
	debug(54, 0) ("ipc(%s,%d): WARNING: %s didn't exit in %d seconds.\n",
	    prog, pid, prog, type == IPC_UDP_SOCKET ? 12 : 5);
    }
    if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) {
	getCurrentTime();
	debug(54, 0)
	    ("ipc(%s,%d): WARNING: ipc_thread_2 didn't exit in 3 seconds.\n",
	    prog, pid);
    }
    getCurrentTime();

    if (!retval)
	debug(54, 2) ("ipc(%s,%d): normal exit\n", prog, pid);

    if (buf1)
	xfree(buf1);

    if (prog)
	xfree(prog);

    if (env_str)
	xfree(env_str);

    if (thread)
	CloseHandle(thread);

    if (hProcess)
	CloseHandle(hProcess);

    if (p2c[0] != -1)
	close(p2c[0]);

    return retval;
}
Beispiel #15
0
/* Emulation of fcntl that supports only F_GETFD and F_SETLKW.  */
int
fcntl (intptr_t fd, int cmd, ...)
{
  va_list ap;

  va_start (ap, cmd);

  switch (cmd)
    {
      case F_GETFD:
        va_end (ap);
        /* Could have used GetHandleInformation, but that isn't
           supported on Windows 9X.  */
        if (_get_osfhandle (fd) == -1)
          return -1;
        return 0;
      case F_SETLKW:
        {
          void *buf = va_arg (ap, void *);
          struct flock *fl = (struct flock *)buf;
          HANDLE hmutex = (HANDLE)fd;
          static struct flock last_fl;
          short last_type = last_fl.l_type;

          va_end (ap);

          if (hmutex == INVALID_HANDLE_VALUE || !hmutex)
            return -1;

          last_fl = *fl;

          switch (fl->l_type)
            {

              case F_WRLCK:
                {
                  DWORD result;

                  if (last_type == F_WRLCK)
                    {
                      /* Don't call WaitForSingleObject if we already
                         own the mutex, because doing so will require
                         us to call ReleaseMutex an equal number of
                         times, before the mutex is actually
                         released.  */
                      return 0;
                    }

                  result = WaitForSingleObject (hmutex, INFINITE);
                  switch (result)
                    {
                      case WAIT_OBJECT_0:
                        /* We don't care if the mutex owner crashed or
                           exited.  */
                      case WAIT_ABANDONED:
                        return 0;
                      case WAIT_FAILED:
                      case WAIT_TIMEOUT: /* cannot happen, really */
                        {
                          DWORD err = GetLastError ();

                          /* Invalidate the last command.  */
                          memset (&last_fl, 0, sizeof (last_fl));

                          switch (err)
                            {
                              case ERROR_INVALID_HANDLE:
                              case ERROR_INVALID_FUNCTION:
                                errno = EINVAL;
                                return -1;
                              default:
                                errno = EDEADLOCK;
                                return -1;
                            }
                        }
                    }
                }
              case F_UNLCK:
                {
                  /* FIXME: Perhaps we should call ReleaseMutex
                     repatedly until it errors out, to make sure the
                     mutext is released even if we somehow managed to
                     to take ownership multiple times?  */
                  BOOL status = ReleaseMutex (hmutex);

                  if (status)
                    return 0;
                  else
                    {
                      DWORD err = GetLastError ();

                      if (err == ERROR_NOT_OWNER)
                        errno = EPERM;
                      else
                        {
                          memset (&last_fl, 0, sizeof (last_fl));
                          errno = EINVAL;
                        }
                      return -1;
                    }
                }
              default:
                errno = ENOSYS;
                return -1;
            }
        }
      default:
        errno = ENOSYS;
        va_end (ap);
        return -1;
    }
}
Beispiel #16
0
int
fdutimens (int fd, char const *file, struct timespec const timespec[2])
{
  struct timespec adjusted_timespec[2];
  struct timespec *ts = timespec ? adjusted_timespec : NULL;
  int adjustment_needed = 0;
  struct stat st;

  if (ts)
    {
      adjusted_timespec[0] = timespec[0];
      adjusted_timespec[1] = timespec[1];
      adjustment_needed = validate_timespec (ts);
    }
  if (adjustment_needed < 0)
    return -1;

  /* Require that at least one of FD or FILE are potentially valid, to avoid
     a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
     than failing.  */
  if (fd < 0 && !file)
    {
      errno = EBADF;
      return -1;
    }

  /* Some Linux-based NFS clients are buggy, and mishandle timestamps
     of files in NFS file systems in some cases.  We have no
     configure-time test for this, but please see
     <https://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
     some of the problems with Linux 2.6.16.  If this affects you,
     compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
     help in some cases, albeit at a cost in performance.  But you
     really should upgrade your kernel to a fixed version, since the
     problem affects many applications.  */

#if HAVE_BUGGY_NFS_TIME_STAMPS
  if (fd < 0)
    sync ();
  else
    fsync (fd);
#endif

  /* POSIX 2008 added two interfaces to set file timestamps with
     nanosecond resolution; newer Linux implements both functions via
     a single syscall.  We provide a fallback for ENOSYS (for example,
     compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
     running on Linux 2.6.18 kernel).  */
#if HAVE_UTIMENSAT || HAVE_FUTIMENS
  if (0 <= utimensat_works_really)
    {
      int result;
# if __linux__ || __sun
      /* As recently as Linux kernel 2.6.32 (Dec 2009), several file
         systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
         but work if both times are either explicitly specified or
         UTIME_NOW.  Work around it with a preparatory [f]stat prior
         to calling futimens/utimensat; fortunately, there is not much
         timing impact due to the extra syscall even on file systems
         where UTIME_OMIT would have worked.

         The same bug occurs in Solaris 11.1 (Apr 2013).

         FIXME: Simplify this for Linux in 2016 and for Solaris in
         2024, when file system bugs are no longer common.  */
      if (adjustment_needed == 2)
        {
          if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
            return -1;
          if (ts[0].tv_nsec == UTIME_OMIT)
            ts[0] = get_stat_atime (&st);
          else if (ts[1].tv_nsec == UTIME_OMIT)
            ts[1] = get_stat_mtime (&st);
          /* Note that st is good, in case utimensat gives ENOSYS.  */
          adjustment_needed++;
        }
# endif
# if HAVE_UTIMENSAT
      if (fd < 0)
        {
          result = utimensat (AT_FDCWD, file, ts, 0);
#  ifdef __linux__
          /* Work around a kernel bug:
             https://bugzilla.redhat.com/show_bug.cgi?id=442352
             https://bugzilla.redhat.com/show_bug.cgi?id=449910
             It appears that utimensat can mistakenly return 280 rather
             than -1 upon ENOSYS failure.
             FIXME: remove in 2010 or whenever the offending kernels
             are no longer in common use.  */
          if (0 < result)
            errno = ENOSYS;
#  endif /* __linux__ */
          if (result == 0 || errno != ENOSYS)
            {
              utimensat_works_really = 1;
              return result;
            }
        }
# endif /* HAVE_UTIMENSAT */
# if HAVE_FUTIMENS
      if (0 <= fd)
        {
          result = futimens (fd, ts);
#  ifdef __linux__
          /* Work around the same bug as above.  */
          if (0 < result)
            errno = ENOSYS;
#  endif /* __linux__ */
          if (result == 0 || errno != ENOSYS)
            {
              utimensat_works_really = 1;
              return result;
            }
        }
# endif /* HAVE_FUTIMENS */
    }
  utimensat_works_really = -1;
  lutimensat_works_really = -1;
#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */

#ifdef USE_SETFILETIME
  /* On native Windows, use SetFileTime(). See
     <https://msdn.microsoft.com/en-us/library/ms724933.aspx>
     <https://msdn.microsoft.com/en-us/library/ms724284.aspx>  */
  if (0 <= fd)
    {
      HANDLE handle;
      FILETIME current_time;
      FILETIME last_access_time;
      FILETIME last_write_time;

      handle = (HANDLE) _get_osfhandle (fd);
      if (handle == INVALID_HANDLE_VALUE)
        {
          errno = EBADF;
          return -1;
        }

      if (ts == NULL || ts[0].tv_nsec == UTIME_NOW || ts[1].tv_nsec == UTIME_NOW)
        {
          /* GetSystemTimeAsFileTime
             <https://msdn.microsoft.com/en-us/library/ms724397.aspx>.
             It would be overkill to use
             GetSystemTimePreciseAsFileTime
             <https://msdn.microsoft.com/en-us/library/hh706895.aspx>.  */
          GetSystemTimeAsFileTime (&current_time);
        }

      if (ts == NULL || ts[0].tv_nsec == UTIME_NOW)
        {
          last_access_time = current_time;
        }
      else if (ts[0].tv_nsec == UTIME_OMIT)
        {
          last_access_time.dwLowDateTime = 0;
          last_access_time.dwHighDateTime = 0;
        }
      else
        {
          ULONGLONG time_since_16010101 =
            (ULONGLONG) ts[0].tv_sec * 10000000 + ts[0].tv_nsec / 100 + 116444736000000000LL;
          last_access_time.dwLowDateTime = (DWORD) time_since_16010101;
          last_access_time.dwHighDateTime = time_since_16010101 >> 32;
        }

      if (ts == NULL || ts[1].tv_nsec == UTIME_NOW)
        {
          last_write_time = current_time;
        }
      else if (ts[1].tv_nsec == UTIME_OMIT)
        {
          last_write_time.dwLowDateTime = 0;
          last_write_time.dwHighDateTime = 0;
        }
      else
        {
          ULONGLONG time_since_16010101 =
            (ULONGLONG) ts[1].tv_sec * 10000000 + ts[1].tv_nsec / 100 + 116444736000000000LL;
          last_write_time.dwLowDateTime = (DWORD) time_since_16010101;
          last_write_time.dwHighDateTime = time_since_16010101 >> 32;
        }

      if (SetFileTime (handle, NULL, &last_access_time, &last_write_time))
        return 0;
      else
        {
          DWORD sft_error = GetLastError ();
          #if 0
          fprintf (stderr, "fdutimens SetFileTime error 0x%x\n", (unsigned int) sft_error);
          #endif
          switch (sft_error)
            {
            case ERROR_ACCESS_DENIED: /* fd was opened without O_RDWR */
              errno = EACCES; /* not specified by POSIX */
              break;
            default:
              errno = EINVAL;
              break;
            }
          return -1;
        }
    }
Beispiel #17
0
U_NO_EXPORT void UProcess::setStdInOutErr(bool fd_stdin, bool fd_stdout, bool fd_stderr)
{
   U_TRACE(1, "UProcess::setStdInOutErr(%b,%b,%b)", fd_stdin, fd_stdout, fd_stderr)

#ifdef __MINGW32__
   HANDLE hProcess = GetCurrentProcess();
#endif

   // check if we write to STDIN

   if (fd_stdin)
      {
#  ifdef __MINGW32__
      if (hFile[1]) // Created parent-output pipe...
         {
         hChildIn = hFile[0];

         // Duplicating as inheritable child-input pipe
         // -------------------------------------------
         // (void) U_SYSCALL(DuplicateHandle, "%p,%p,%p,%p,%lu,%b,%lu", hProcess, hFile[0], hProcess, &hChildIn, 0, TRUE, DUPLICATE_SAME_ACCESS);
         // (void) U_SYSCALL(    CloseHandle, "%p",                               hFile[0]);
         }
      else
         {
         hChildIn = (HANDLE)_get_osfhandle(filedes[0]);
         }
#  else
      U_INTERNAL_ASSERT_MAJOR(filedes[0],STDERR_FILENO)

      (void) U_SYSCALL(dup2, "%d,%d", filedes[0], STDIN_FILENO);

      U_INTERNAL_ASSERT_EQUALS(::fcntl(STDIN_FILENO,F_GETFD,FD_CLOEXEC), 0)
#  endif
      }

   // check if we read from STDOUT

   if (fd_stdout)
      {
#  ifdef __MINGW32__
      if (hFile[2]) // Created parent-input pipe...
         {
         hChildOut = hFile[3];

         // Duplicating as inheritable child-output pipe
         // -------------------------------------------
         // (void) U_SYSCALL(DuplicateHandle, "%p,%p,%p,%p,%lu,%b,%lu", hProcess, hFile[3], hProcess, &hChildOut, 0, TRUE, DUPLICATE_SAME_ACCESS);
         // (void) U_SYSCALL(    CloseHandle, "%p",                               hFile[3]);
         }
      else
         {
         hChildOut = (HANDLE)_get_osfhandle(filedes[3]);
         }
#  else
      U_INTERNAL_ASSERT_MAJOR(filedes[3],STDOUT_FILENO)

      (void) U_SYSCALL(dup2, "%d,%d", filedes[3], STDOUT_FILENO);

      U_INTERNAL_ASSERT_EQUALS(::fcntl(STDOUT_FILENO,F_GETFD,FD_CLOEXEC), 0)
#  endif
      }

   // check if we read from STDERR

   if (fd_stderr)
      {
#  ifdef __MINGW32__
      if (hFile[4]) // Created parent-input pipe...
         {
         hChildErr = hFile[5];

         // Duplicating as inheritable child-output pipe
         // -------------------------------------------
         // (void) U_SYSCALL(DuplicateHandle, "%p,%p,%p,%p,%lu,%b,%lu", hProcess, hFile[5], hProcess, &hChildErr, 0, TRUE, DUPLICATE_SAME_ACCESS);
         // (void) U_SYSCALL(    CloseHandle, "%p",                               hFile[5]);
         }
      else
         {
         hChildErr = (HANDLE)_get_osfhandle(filedes[5]);
         }
#  else
      U_INTERNAL_ASSERT(filedes[5] >= STDOUT_FILENO)

      (void) U_SYSCALL(dup2, "%d,%d", filedes[5], STDERR_FILENO);

      U_INTERNAL_ASSERT_EQUALS(::fcntl(STDERR_FILENO,F_GETFD,FD_CLOEXEC), 0)
#  endif
      }

#ifdef __MINGW32__
   CloseHandle(hProcess);
#else
   if (fd_stdin)
      {
      U_INTERNAL_DUMP("filedes[0,1] = { %d, %d }", filedes[0], filedes[1])

                                      (void) U_SYSCALL(close, "%d", filedes[0]);
      if (filedes[1] > STDERR_FILENO) (void) U_SYSCALL(close, "%d", filedes[1]);
      }

   if (fd_stdout)
      {
      U_INTERNAL_DUMP("filedes[2,3] = { %d, %d }", filedes[2], filedes[3])

                                       (void) U_SYSCALL(close, "%d", filedes[3]);
      if (filedes[2] > STDERR_FILENO)  (void) U_SYSCALL(close, "%d", filedes[2]);
      }

   if (fd_stderr)
      {
      U_INTERNAL_DUMP("filedes[4,5] = { %d, %d }", filedes[4], filedes[5])

                                       (void) U_SYSCALL(close, "%d", filedes[5]);
      if (filedes[4] > STDERR_FILENO)  (void) U_SYSCALL(close, "%d", filedes[4]);
      }
#endif
}
Beispiel #18
0
int uv_is_tty(uv_file file) {
  DWORD result;
  return GetConsoleMode((HANDLE) _get_osfhandle(file), &result) != 0;
}
Beispiel #19
0
/* Simplified version of gnupg_spawn_process.  This function forks and
   then execs PGMNAME, while connecting INFD to stdin, OUTFD to stdout
   and ERRFD to stderr (any of them may be -1 to connect them to
   /dev/null).  The arguments for the process are expected in the NULL
   terminated array ARGV.  The program name itself should not be
   included there.  Calling gnupg_wait_process is required.

   Returns 0 on success or an error code. */
gpg_error_t
gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
                        int infd, int outfd, int errfd, pid_t *pid)
{
  gpg_error_t err;
  SECURITY_ATTRIBUTES sec_attr;
  PROCESS_INFORMATION pi = { NULL, 0, 0, 0 };
  STARTUPINFO si;
  char *cmdline;
  int i;
  HANDLE stdhd[3];

  /* Setup return values.  */
  *pid = (pid_t)(-1);

  /* Prepare security attributes.  */
  memset (&sec_attr, 0, sizeof sec_attr );
  sec_attr.nLength = sizeof sec_attr;
  sec_attr.bInheritHandle = FALSE;

  /* Build the command line.  */
  err = build_w32_commandline (pgmname, argv, &cmdline);
  if (err)
    return err;

  memset (&si, 0, sizeof si);
  si.cb = sizeof (si);
  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  si.wShowWindow = DEBUG_W32_SPAWN? SW_SHOW : SW_MINIMIZE;
  stdhd[0] = infd  == -1? w32_open_null (0) : INVALID_HANDLE_VALUE;
  stdhd[1] = outfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
  stdhd[2] = errfd == -1? w32_open_null (1) : INVALID_HANDLE_VALUE;
  si.hStdInput  = infd  == -1? stdhd[0] : (void*)_get_osfhandle (infd);
  si.hStdOutput = outfd == -1? stdhd[1] : (void*)_get_osfhandle (outfd);
  si.hStdError  = errfd == -1? stdhd[2] : (void*)_get_osfhandle (errfd);

/*   log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
  if (!CreateProcess (pgmname,       /* Program to start.  */
                      cmdline,       /* Command line arguments.  */
                      &sec_attr,     /* Process security attributes.  */
                      &sec_attr,     /* Thread security attributes.  */
                      TRUE,          /* Inherit handles.  */
                      (CREATE_DEFAULT_ERROR_MODE
                       | GetPriorityClass (GetCurrentProcess ())
                       | CREATE_SUSPENDED | DETACHED_PROCESS),
                      NULL,          /* Environment.  */
                      NULL,          /* Use current drive/directory.  */
                      &si,           /* Startup information. */
                      &pi            /* Returns process information.  */
                      ))
    {
      log_error ("CreateProcess failed: %s\n", w32_strerror (-1));
      err = gpg_error (GPG_ERR_GENERAL);
    }
  else
    err = 0;
  xfree (cmdline);
  for (i=0; i < 3; i++)
    if (stdhd[i] != INVALID_HANDLE_VALUE)
      CloseHandle (stdhd[i]);
  if (err)
    return err;

/*   log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
/*              " dwProcessID=%d dwThreadId=%d\n", */
/*              pi.hProcess, pi.hThread, */
/*              (int) pi.dwProcessId, (int) pi.dwThreadId); */

  /* Process has been created suspended; resume it now. */
  ResumeThread (pi.hThread);
  CloseHandle (pi.hThread);

  *pid = handle_to_pid (pi.hProcess);
  return 0;

}
Beispiel #20
0
/* Win32 select() will only work with sockets, so we roll our own implementation here.
 * - If you supply only sockets, this simply passes through to winsock select().
 * - If you supply file handles, there is no way to distinguish between
 *   ready for read/write or OOB, so any set in which the handle is found will
 *   be marked as ready.
 * - If you supply a mixture of handles and sockets, the system will interleave
 *   calls between select() and WaitForMultipleObjects(). The time slicing may
 *   cause this function call to take up to 100 ms longer than you specified.
 * - Calling this with NULL sets as a portable way to sleep with sub-second
 *   accuracy is not supported.
 * */
PHPAPI int php_select(int max_fd, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *tv)
{
	DWORD ms_total, limit;
	HANDLE handles[MAXIMUM_WAIT_OBJECTS];
	int handle_slot_to_fd[MAXIMUM_WAIT_OBJECTS];
	int n_handles = 0, i;
	fd_set sock_read, sock_write, sock_except;
	fd_set aread, awrite, aexcept;
	int sock_max_fd = -1;
	struct timeval tvslice;
	int retcode;

#define SAFE_FD_ISSET(fd, set)	(set != NULL && FD_ISSET(fd, set))
	
	/* calculate how long we need to wait in milliseconds */
	if (tv == NULL) {
		ms_total = INFINITE;
	} else {
		ms_total = tv->tv_sec * 1000;
		ms_total += tv->tv_usec / 1000;
	}

	FD_ZERO(&sock_read);
	FD_ZERO(&sock_write);
	FD_ZERO(&sock_except);
	
	/* build an array of handles for non-sockets */
	for (i = 0; i < max_fd; i++) {
		if (SAFE_FD_ISSET(i, rfds) || SAFE_FD_ISSET(i, wfds) || SAFE_FD_ISSET(i, efds)) {
			handles[n_handles] = (HANDLE)(zend_uintptr_t)_get_osfhandle(i);
			if (handles[n_handles] == INVALID_HANDLE_VALUE) {
				/* socket */
				if (SAFE_FD_ISSET(i, rfds)) {
					FD_SET((uint)i, &sock_read);
				}
				if (SAFE_FD_ISSET(i, wfds)) {
					FD_SET((uint)i, &sock_write);
				}
				if (SAFE_FD_ISSET(i, efds)) {
					FD_SET((uint)i, &sock_except);
				}
				if (i > sock_max_fd) {
					sock_max_fd = i;
				}
			} else {
				handle_slot_to_fd[n_handles] = i;
				n_handles++;
			}
		}
	}

	if (n_handles == 0) {
		/* plain sockets only - let winsock handle the whole thing */
		return select(max_fd, rfds, wfds, efds, tv);
	}
	
	/* mixture of handles and sockets; lets multiplex between
	 * winsock and waiting on the handles */

	FD_ZERO(&aread);
	FD_ZERO(&awrite);
	FD_ZERO(&aexcept);
	
	limit = GetTickCount() + ms_total;
	do {
		retcode = 0;
	
		if (sock_max_fd >= 0) {
			/* overwrite the zero'd sets here; the select call
			 * will clear those that are not active */
			aread = sock_read;
			awrite = sock_write;
			aexcept = sock_except;

			tvslice.tv_sec = 0;
			tvslice.tv_usec = 100000;

			retcode = select(sock_max_fd+1, &aread, &awrite, &aexcept, &tvslice);
		}
		if (n_handles > 0) {
			/* check handles */
			DWORD wret;

			wret = MsgWaitForMultipleObjects(n_handles, handles, FALSE, retcode > 0 ? 0 : 100, QS_ALLEVENTS);

			if (wret == WAIT_TIMEOUT) {
				/* set retcode to 0; this is the default.
				 * select() may have set it to something else,
				 * in which case we leave it alone, so this branch
				 * does nothing */
				;
			} else if (wret == WAIT_FAILED) {
				if (retcode == 0) {
					retcode = -1;
				}
			} else {
				if (retcode < 0) {
					retcode = 0;
				}
				for (i = 0; i < n_handles; i++) {
					if (WAIT_OBJECT_0 == WaitForSingleObject(handles[i], 0)) {
						if (SAFE_FD_ISSET(handle_slot_to_fd[i], rfds)) {
							FD_SET((uint)handle_slot_to_fd[i], &aread);
						}
						if (SAFE_FD_ISSET(handle_slot_to_fd[i], wfds)) {
							FD_SET((uint)handle_slot_to_fd[i], &awrite);
						}
						if (SAFE_FD_ISSET(handle_slot_to_fd[i], efds)) {
							FD_SET((uint)handle_slot_to_fd[i], &aexcept);
						}
						retcode++;
					}
				}
			}
		}
	} while (retcode == 0 && (ms_total == INFINITE || GetTickCount() < limit));

	if (rfds) {
		*rfds = aread;
	}
	if (wfds) {
		*wfds = awrite;
	}
	if (efds) {
		*efds = aexcept;
	}	
	
	return retcode;
}
Beispiel #21
0
static void copy_file_attributes(int infd, int outfd, const char *outfile)
{
#ifdef WIN32
    BY_HANDLE_FILE_INFORMATION fi;
    BOOL bOk;

    bOk = GetFileInformationByHandle((HANDLE)_get_osfhandle(infd), &fi);
    trace("GetFileInformationByHandle(...) => %s\n", bOk ? "TRUE" : "FALSE");
    if (bOk) {
        bOk = SetFileTime((HANDLE)_get_osfhandle(outfd), NULL, &fi.ftLastAccessTime, &fi.ftLastWriteTime);
        trace("SetFileTime(...) => %s\n", bOk ? "TRUE" : "FALSE");
        bOk = SetFileAttributesA(outfile, fi.dwFileAttributes);
        trace("SetFileAttributesA(...) => %s\n", bOk ? "TRUE" : "FALSE");
    }
#else
    struct stat sbuf;
#ifdef HAVE_FUTIMENS
    struct timespec times[2];
#else
    struct timeval times[2];
#endif
    int rv;

    if ((rv = fstat(infd, &sbuf)) != 0) {
        trace("fstat(%d, &sbuf) => %d (errno = %d)\n",
              infd, rv, errno);
        return;
    }

    /* copy file times. */
#ifdef HAVE_FUTIMENS
    times[0].tv_sec = sbuf.st_atime;
    times[0].tv_nsec = SNZ_ST_TIME_NSEC(sbuf, a);
    times[1].tv_sec = sbuf.st_mtime;
    times[1].tv_nsec = SNZ_ST_TIME_NSEC(sbuf, m);
    rv = futimens(outfd, times);
    trace("futimens(%d, [{%ld, %ld}, {%ld, %ld}]) => %d\n",
          outfd, times[0].tv_sec, times[0].tv_nsec,
          times[1].tv_sec, times[1].tv_nsec, rv);
#else /* HAVE_FUTIMENS */
    times[0].tv_sec = sbuf.st_atime;
    times[0].tv_usec = SNZ_ST_TIME_NSEC(sbuf, a) / 1000;
    times[1].tv_sec = sbuf.st_mtime;
    times[1].tv_usec = SNZ_ST_TIME_NSEC(sbuf, m) / 1000;
#ifdef HAVE_FUTIMES
    rv = futimes(outfd, times);
    trace("futimes(%d, [{%ld, %ld}, {%ld, %ld}]) => %d\n",
          outfd, times[0].tv_sec, times[0].tv_usec,
          times[1].tv_sec, times[1].tv_usec, rv);
#else /* HAVE_FUTIMES */
    rv = utimes(outfile, times);
    trace("utimes(\"%s\", [{%ld, %ld}, {%ld, %ld}]) => %d\n",
          outfile, times[0].tv_sec, times[0].tv_usec,
          times[1].tv_sec, times[1].tv_usec, rv);
#endif /* HAVE_FUTIMES */
#endif /* HAVE_FUTIMENS */

    /* copy other attributes */
    rv = fchown(outfd, sbuf.st_uid, sbuf.st_gid);
    trace("fchown(%d, %d, %d) => %d\n",
          outfd, sbuf.st_uid, sbuf.st_gid, rv);
    rv = fchmod(outfd, sbuf.st_mode);
    trace("fchmod(%d, 0%o) => %d\n",
          outfd, sbuf.st_mode, rv);
#endif
}
Beispiel #22
0
char *FILE_name(FILE *o, char buf[CFW_MAX_PATH])
{
    // (attempts to) copy a filename into buf from a FILE handle
    // (this is only used for debug output)
    UNUSED(o);
    
    
#ifdef TARGET_LINUX
    char procbuf[CFW_MAX_PATH];
    
    int fd = fileno(o);
    if (fd == -1) { goto err; }
    
    sprintf(procbuf, "/proc/self/fd/%d", fd);
    ssize_t r = readlink(procbuf, buf, CFW_MAX_PATH-2);
    if (r < 0) { goto err; }
    buf[CFW_MAX_PATH-1] = '\0';
    
    return buf;
    
    err:
#endif


#ifdef TARGET_WINDOWS
    
    // Works on Vista and above only; doesn't work on wine
    // https://gist.github.com/PolarNick239/5168c2bbf2731171bc190a465cc4d052
    HINSTANCE hKernel32;
    DWORD (CALLBACK *future_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, DWORD);
    hKernel32 = GetModuleHandleA("KERNEL32");
    if (!hKernel32)
    {
        // INFO("Missing KERNEL32");
        goto err;
    }
    *(FARPROC*)&future_GetFinalPathNameByHandleA = GetProcAddress(hKernel32, "GetFinalPathNameByHandleA");
    if (!future_GetFinalPathNameByHandleA)
    {
        // INFO("Missing GetFinalPathNameByHandleA");
        goto err;
    }

    int fd = fileno(o);
    if (fd == -1) { goto err; }
    
    intptr_t ihandle = _get_osfhandle(fd);
    if (ihandle == -1) { goto err; }
    HANDLE handle = (HANDLE) ihandle;

    UNUSED(handle);
    unsigned int result = future_GetFinalPathNameByHandleA(handle, buf, CFW_MAX_PATH-2, 0);

    // result can fail in many ways! =0, or > len
    // https://docs.microsoft.com/en-gb/windows/desktop/api/fileapi/nf-fileapi-getfinalpathnamebyhandlea

    if ((result == 0) || (result > CFW_MAX_PATH-2)) { goto err; }

    return buf;

    err:
#endif
    
        strcpy(buf, "unknown stream");
        return buf;
}
Beispiel #23
0
static uint64_t
id_from_fd (const int fd)
{
  return id_from_handle ((HANDLE) _get_osfhandle (fd));
}
Beispiel #24
0
CStdioFile::CStdioFile(FILE* pOpenStream) : CFile(hFileNull)
{
	m_pStream = pOpenStream;
	m_hFile = (UINT)_get_osfhandle(_fileno(pOpenStream));
	ASSERT(!m_bCloseOnDelete);
}
Beispiel #25
0
 long xbp__get_osfhandle(int fd)
 {
   return _get_osfhandle(fd);
 }
Beispiel #26
0
extern jlib_decl size32_t checked_pread(int file, void *buffer, size32_t len, offset_t pos)
{
    if (0==len) return 0;
#ifdef WIN32
    if (atomicsupported)
    {
        HANDLE hFile = (HANDLE)_get_osfhandle(file);
        DWORD rread;
        OVERLAPPED overlapped;
        memset(&overlapped, 0, sizeof(overlapped));
        overlapped.Offset = (DWORD) pos;
        overlapped.OffsetHigh = (DWORD)(pos>>32);
        if (ReadFile(hFile, buffer, len, &rread, &overlapped))
            return rread;
        int err = (int)GetLastError();
        if (err == ERROR_HANDLE_EOF)
            return 0;
        if (err == ERROR_INVALID_PARAMETER) // Win98 etc
            atomicsupported = false;
        else
            throw makeOsException(GetLastError(), "checked_pread");
    }
    {
        CriticalBlock blk(atomicsection);
        checked_lseeki64(file, pos, FILE_BEGIN);
        return checked_read(file, buffer, len);
    }
#else
    size32_t ret = 0;
    unsigned attempts = 0;
    unsigned __int64 startCycles = get_cycles_now();
    loop
    {
        ssize_t readNow = ::pread(file, buffer, len, pos);
        if (readNow == (ssize_t)-1)
        {
            switch (errno)
            {
            case EINTR:
                readNow = 0;
                break;
            default:
                if (attempts < ioRetryCount)
                {
                    attempts++;
                    StringBuffer callStr("pread");
                    callStr.append("[errno=").append(errno);
                    unsigned __int64 elapsedMs = cycle_to_nanosec(get_cycles_now() - startCycles)/1000000;
                    callStr.append(", took=").append(elapsedMs);
                    callStr.append(", attempt=").append(attempts).append("](handle=");
                    callStr.append(file).append(", pos=").append(pos).append(", len=").append(len).append(")");
                    PROGLOG("%s", callStr.str());
                    readNow = 0;
                    break;
                }
                throw makeErrnoException(errno, "checked_pread");
            }
        }
        else if (!readNow)
            break;
        ret += readNow;
        if (readNow == (ssize_t)len)
            break;
        pos += readNow;
        buffer = ((char *) buffer) + readNow;
        len -= readNow;
    }
    return ret;
#endif
}
Beispiel #27
0
int
win32execute(char *path, char **argv, int doreturn,
             int fd_stdout, int fd_stderr)
{
	PROCESS_INFORMATION pi;
	memset(&pi, 0x00, sizeof(pi));

	STARTUPINFO si;
	memset(&si, 0x00, sizeof(si));

	char *sh = win32getshell(path);
	if (sh) {
		path = sh;
	}

	si.cb = sizeof(STARTUPINFO);
	if (fd_stdout != -1) {
		si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout);
		si.hStdError = (HANDLE)_get_osfhandle(fd_stderr);
		si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
		si.dwFlags = STARTF_USESTDHANDLES;
		if (si.hStdOutput == INVALID_HANDLE_VALUE
		    || si.hStdError == INVALID_HANDLE_VALUE) {
			return -1;
		}
	} else {
		// Redirect subprocess stdout, stderr into current process.
		si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
		si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
		si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
		si.dwFlags = STARTF_USESTDHANDLES;
		if (si.hStdOutput == INVALID_HANDLE_VALUE
		    || si.hStdError == INVALID_HANDLE_VALUE) {
			return -1;
		}
	}

	char *args = win32argvtos(sh, argv);
	const char *ext = strrchr(path, '.');
	char full_path_win_ext[MAX_PATH] = {0};
	add_exe_ext_if_no_to_fullpath(full_path_win_ext, MAX_PATH, ext, path);
	BOOL ret =
	  CreateProcess(full_path_win_ext, args, NULL, NULL, 1, 0, NULL, NULL,
	                &si, &pi);
	if (fd_stdout != -1) {
		close(fd_stdout);
		close(fd_stderr);
	}
	free(args);
	if (ret == 0) {
		LPVOID lpMsgBuf;
		DWORD dw = GetLastError();
		FormatMessage(
		  FORMAT_MESSAGE_ALLOCATE_BUFFER |
		  FORMAT_MESSAGE_FROM_SYSTEM |
		  FORMAT_MESSAGE_IGNORE_INSERTS,
		  NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,
		  0, NULL);

		LPVOID lpDisplayBuf =
		  (LPVOID) LocalAlloc(LMEM_ZEROINIT,
		                      (lstrlen((LPCTSTR) lpMsgBuf)
		                       + lstrlen((LPCTSTR) __FILE__) + 200)
		                      * sizeof(TCHAR));
		_snprintf((LPTSTR) lpDisplayBuf,
		          LocalSize(lpDisplayBuf) / sizeof(TCHAR),
		          TEXT("%s failed with error %lu: %s"), __FILE__, dw,
		          (const char *)lpMsgBuf);

		cc_log("can't execute %s; OS returned error: %s",
		       full_path_win_ext, (char *)lpDisplayBuf);

		LocalFree(lpMsgBuf);
		LocalFree(lpDisplayBuf);

		return -1;
	}
	WaitForSingleObject(pi.hProcess, INFINITE);

	DWORD exitcode;
	GetExitCodeProcess(pi.hProcess, &exitcode);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	if (!doreturn) {
		x_exit(exitcode);
	}
	return exitcode;
}
Beispiel #28
0
int
rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
            struct timeval *timeout)
#undef timeval
{
  static struct timeval tv0;
  static HANDLE hEvent;
  HANDLE h, handle_array[FD_SETSIZE + 2];
  fd_set handle_rfds, handle_wfds, handle_xfds;
  struct bitset rbits, wbits, xbits;
  unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
  DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
  MSG msg;
  int i, fd, rc;

  if (nfds > FD_SETSIZE)
    nfds = FD_SETSIZE;

  if (!timeout)
    wait_timeout = INFINITE;
  else
    {
      wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;

      /* select is also used as a portable usleep.  */
      if (!rfds && !wfds && !xfds)
        {
          Sleep (wait_timeout);
          return 0;
        }
    }

  if (!hEvent)
    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);

  handle_array[0] = hEvent;
  nhandles = 1;
  nsock = 0;

  /* Copy descriptors to bitsets.  At the same time, eliminate
     bits in the "wrong" direction for console input buffers
     and screen buffers, because screen buffers are waitable
     and they will block until a character is available.  */
  memset (&rbits, 0, sizeof (rbits));
  memset (&wbits, 0, sizeof (wbits));
  memset (&xbits, 0, sizeof (xbits));
  memset (anyfds_in, 0, sizeof (anyfds_in));
  if (rfds)
    for (i = 0; i < rfds->fd_count; i++)
      {
        fd = rfds->fd_array[i];
        h = (HANDLE) _get_osfhandle (fd);
        if (IsConsoleHandle (h)
            && !GetNumberOfConsoleInputEvents (h, &nbuffer))
          continue;

        rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
      }
  else
    rfds = (fd_set *) alloca (sizeof (fd_set));

  if (wfds)
    for (i = 0; i < wfds->fd_count; i++)
      {
        fd = wfds->fd_array[i];
        h = (HANDLE) _get_osfhandle (fd);
        if (IsConsoleHandle (h)
            && GetNumberOfConsoleInputEvents (h, &nbuffer))
          continue;

        wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
      }
  else
    wfds = (fd_set *) alloca (sizeof (fd_set));

  if (xfds)
    for (i = 0; i < xfds->fd_count; i++)
      {
        fd = xfds->fd_array[i];
        xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
      }
  else
    xfds = (fd_set *) alloca (sizeof (fd_set));

  /* Zero all the fd_sets, including the application's.  */
  FD_ZERO (rfds);
  FD_ZERO (wfds);
  FD_ZERO (xfds);
  FD_ZERO (&handle_rfds);
  FD_ZERO (&handle_wfds);
  FD_ZERO (&handle_xfds);

  /* Classify handles.  Create fd sets for sockets, poll the others. */
  for (i = 0; i < nfds; i++)
    {
      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
        continue;

      h = (HANDLE) _get_osfhandle (i);
      if (!h)
        {
          errno = EBADF;
          return -1;
        }

      if (IsSocketHandle (h))
        {
          int requested = FD_CLOSE;

          /* See above; socket handles are mapped onto select, but we
             need to map descriptors to handles.  */
          if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            {
              requested |= FD_READ | FD_ACCEPT;
              FD_SET ((SOCKET) h, rfds);
              FD_SET ((SOCKET) h, &handle_rfds);
            }
          if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            {
              requested |= FD_WRITE | FD_CONNECT;
              FD_SET ((SOCKET) h, wfds);
              FD_SET ((SOCKET) h, &handle_wfds);
            }
          if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            {
              requested |= FD_OOB;
              FD_SET ((SOCKET) h, xfds);
              FD_SET ((SOCKET) h, &handle_xfds);
            }

          WSAEventSelect ((SOCKET) h, hEvent, requested);
          nsock++;
        }
      else
        {
          handle_array[nhandles++] = h;

          /* Poll now.  If we get an event, do not wait below.  */
          if (wait_timeout != 0
              && windows_poll_handle (h, i, &rbits, &wbits, &xbits))
            wait_timeout = 0;
        }
    }

  /* Place a sentinel at the end of the array.  */
  handle_array[nhandles] = NULL;

restart:
  if (wait_timeout == 0 || nsock == 0)
    rc = 0;
  else
    {
      /* See if we need to wait in the loop below.  If any select is ready,
         do MsgWaitForMultipleObjects anyway to dispatch messages, but
         no need to call select again.  */
      rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
      if (rc == 0)
        {
          /* Restore the fd_sets for the other select we do below.  */
          memcpy (&handle_rfds, rfds, sizeof (fd_set));
          memcpy (&handle_wfds, wfds, sizeof (fd_set));
          memcpy (&handle_xfds, xfds, sizeof (fd_set));
        }
      else
        wait_timeout = 0;
    }

  for (;;)
    {
      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
                                       wait_timeout, QS_ALLINPUT);

      if (ret == WAIT_OBJECT_0 + nhandles)
        {
          /* new input of some other kind */
          BOOL bRet;
          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
            {
              TranslateMessage (&msg);
              DispatchMessage (&msg);
            }
        }
      else
        break;
    }

  /* If we haven't done it yet, check the status of the sockets.  */
  if (rc == 0 && nsock > 0)
    rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);

  if (nhandles > 1)
    {
      /* Count results that are not counted in the return value of select.  */
      nhandles = 1;
      for (i = 0; i < nfds; i++)
        {
          if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
            continue;

          h = (HANDLE) _get_osfhandle (i);
          if (h == handle_array[nhandles])
            {
              /* Not a socket.  */
              nhandles++;
              windows_poll_handle (h, i, &rbits, &wbits, &xbits);
              if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
                  || wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))
                  || xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
                rc++;
            }
        }

      if (rc == 0 && wait_timeout == INFINITE)
        {
          /* Sleep 1 millisecond to avoid busy wait and retry with the
             original fd_sets.  */
          memcpy (&handle_rfds, rfds, sizeof (fd_set));
          memcpy (&handle_wfds, wfds, sizeof (fd_set));
          memcpy (&handle_xfds, xfds, sizeof (fd_set));
          SleepEx (1, TRUE);
          goto restart;
        }
    }

  /* Now fill in the results.  */
  FD_ZERO (rfds);
  FD_ZERO (wfds);
  FD_ZERO (xfds);
  nhandles = 1;
  for (i = 0; i < nfds; i++)
    {
      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
        continue;

      h = (HANDLE) _get_osfhandle (i);
      if (h != handle_array[nhandles])
        {
          /* Perform handle->descriptor mapping.  */
          WSAEventSelect ((SOCKET) h, NULL, 0);
          if (FD_ISSET (h, &handle_rfds))
            FD_SET (i, rfds);
          if (FD_ISSET (h, &handle_wfds))
            FD_SET (i, wfds);
          if (FD_ISSET (h, &handle_xfds))
            FD_SET (i, xfds);
        }
      else
        {
          /* Not a socket.  */
          nhandles++;
          if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            FD_SET (i, rfds);
          if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            FD_SET (i, wfds);
          if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
            FD_SET (i, xfds);
        }
    }

  return rc;
}
/* this is the read handler for my own child procs and stdin
 */
void orte_iof_mrhnp_read_local_handler(int fd, short event, void *cbdata)
{
    orte_iof_read_event_t *rev = (orte_iof_read_event_t*)cbdata;
    unsigned char data[ORTE_IOF_BASE_MSG_MAX];
    int32_t numbytes;
    opal_list_item_t *item;
    orte_iof_proc_t *proct;
    int i, j;
    orte_ns_cmp_bitmask_t mask;
    orte_job_t *jdata;
    orte_iof_job_t *iofjob;
    orte_node_t *node;
    orte_proc_t *daemon;
    orte_job_map_t *map;
    bool write_out=false;

    /* read up to the fragment size */
#if !defined(__WINDOWS__)
    numbytes = read(fd, data, sizeof(data));
#else
    {
        DWORD readed;
        HANDLE handle = (HANDLE)_get_osfhandle(fd);
        ReadFile(handle, data, sizeof(data), &readed, NULL);
        numbytes = (int)readed;
    }
#endif  /* !defined(__WINDOWS__) */
    
    OPAL_OUTPUT_VERBOSE((1, orte_iof_base.iof_output,
                         "%s iof:mrhnp:read handler read %d bytes from %s:%d",
                         ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), numbytes,
                         ORTE_NAME_PRINT(&rev->name), fd));

    if (numbytes < 0) {
        /* either we have a connection error or it was a non-blocking read */
        
        /* non-blocking, retry */
        if (EAGAIN == errno || EINTR == errno) {
            opal_event_add(rev->ev, 0);
            return;
        } 

        OPAL_OUTPUT_VERBOSE((1, orte_iof_base.iof_output,
                             "%s iof:mrhnp:read handler %s Error on connection:%d",
                             ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
                             ORTE_NAME_PRINT(&rev->name), fd));
        /* Un-recoverable error. Allow the code to flow as usual in order to
         * to send the zero bytes message up the stream, and then close the
         * file descriptor and delete the event.
         */
        numbytes = 0;
    }
    
    /* if job termination has been ordered, just ignore the
     * data and delete the stdin read event, if that is what fired
     */
    if (orte_job_term_ordered) {
        if (ORTE_IOF_STDIN & rev->tag) {
            OBJ_RELEASE(mca_iof_mr_hnp_component.stdinev);
        }
        return;
    }

    if (ORTE_IOF_STDIN & rev->tag) {
        /* The event has fired, so it's no longer active until we
         * re-add it
         */
        mca_iof_mr_hnp_component.stdinev->active = false;    
        /* if this was read from my stdin, I need to send this input to all
         * daemons who host mapper procs
         */
        for (j=0; j < mca_iof_mr_hnp_component.stdin_jobs.size; j++) {
            if (NULL == (iofjob = (orte_iof_job_t*)opal_pointer_array_get_item(&mca_iof_mr_hnp_component.stdin_jobs, j))) {
                continue;
            }
            jdata = iofjob->jdata;
            OPAL_OUTPUT_VERBOSE((1, orte_iof_base.iof_output,
                                 "%s read %d bytes from stdin - writing to job %s",
                                 ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), numbytes,
                                 ORTE_JOBID_PRINT(jdata->jobid)));
            map = jdata->map;
            for (i=0; i < map->nodes->size; i++) {
                if (NULL == (node = (orte_node_t*)opal_pointer_array_get_item(map->nodes, i))) {
                    continue;
                }
                daemon = node->daemon;

                if (daemon->name.vpid == ORTE_PROC_MY_NAME->vpid) {
                    /* if it is me, then send the bytes down the stdin pipe
                     * for every local proc (they are all on my proct list) - we even send 0 byte events
                     * down the pipe so it forces out any preceding data before
                     * closing the output stream. We add a 0 byte message if
                     * numbytes < sizeof(data) as this means the chunk we read
                     * was the end of the file.
                     */
                    for (item = opal_list_get_first(&mca_iof_mr_hnp_component.procs);
                         item != opal_list_get_end(&mca_iof_mr_hnp_component.procs);
                         item = opal_list_get_next(item)) {
                        proct = (orte_iof_proc_t*)item;
                        if (proct->name.jobid == jdata->jobid) {
                            if (NULL == proct->sink) {
                                opal_output(0, "NULL SINK FOR PROC %s", ORTE_NAME_PRINT(&proct->name));
                                continue;
                            }
                            if (ORTE_IOF_MAX_INPUT_BUFFERS < orte_iof_base_write_output(&proct->name, ORTE_IOF_STDIN, data, numbytes, proct->sink->wev)) {
                                /* getting too backed up - stop the read event for now if it is still active */
                                if (mca_iof_mr_hnp_component.stdinev->active) {
                                    OPAL_OUTPUT_VERBOSE((1, orte_iof_base.iof_output,
                                                         "buffer backed up - holding"));
                                    mca_iof_mr_hnp_component.stdinev->active = false;
                                }
                                return;
                            }
                            if (0 < numbytes && numbytes < (int)sizeof(data)) {
                                /* need to write a 0-byte event to clear the stream and close it */
                                orte_iof_base_write_output(&proct->name, ORTE_IOF_STDIN, data, 0, proct->sink->wev);
                                proct->sink = NULL;
                            }
                        }
                    }
                } else {
                    OPAL_OUTPUT_VERBOSE((1, orte_iof_base.iof_output,
                                         "%s sending %d bytes from stdin to daemon %s",
                                         ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), numbytes,
                                         ORTE_NAME_PRINT(&daemon->name)));
                
                    /* send the data to the daemon so it can
                     * write it to all local procs from this job.
                     * If the connection closed,
                     * numbytes will be zero so zero bytes will be
                     * sent - this will tell the daemon to close
                     * the fd for stdin to that proc
                     */
                    send_data(&daemon->name, ORTE_IOF_STDIN, jdata->jobid, data, numbytes);
                    if (0 < numbytes && numbytes < (int)sizeof(data)) {
                        /* need to send a 0-byte message to clear the stream and close it */
                        send_data(&daemon->name, ORTE_IOF_STDIN, jdata->jobid, data, 0);
                    }
                }
            }
        }
        /* if num_bytes was zero, then we need to terminate the event */
        if (0 == numbytes || numbytes < (int)sizeof(data)) {
            /* this will also close our stdin file descriptor */
            if (NULL != mca_iof_mr_hnp_component.stdinev) {
                OBJ_RELEASE(mca_iof_mr_hnp_component.stdinev);
            }
        } else {
            /* if we are looking at a tty, then we just go ahead and restart the
             * read event assuming we are not backgrounded
             */
            if (orte_iof_mrhnp_stdin_check(fd)) {
                restart_stdin(fd, 0, NULL);
            } else {
                /* delay for awhile and then restart */
                ORTE_TIMER_EVENT(0, 10000, restart_stdin, ORTE_INFO_PRI);
            }
        }
        return;
    }

    if (ORTE_IOF_STDOUT & rev->tag && 0 < numbytes) {
        /* see if we need to forward this output */
        jdata = orte_get_job_data_object(rev->name.jobid);
        if (ORTE_JOBID_INVALID == jdata->stdout_target) {
            /* end of the chain - just output the info */
            write_out = true;
            goto PROCESS;
        }
        /* it goes to the next job in the chain */
        jdata = orte_get_job_data_object(jdata->stdout_target);
        map = jdata->map;
        for (i=0; i < map->nodes->size; i++) {
            if (NULL == (node = (orte_node_t*)opal_pointer_array_get_item(map->nodes, i))) {
                continue;
            }
            daemon = node->daemon;

            if (daemon->name.vpid == ORTE_PROC_MY_NAME->vpid) {
                /* if it is me, then send the bytes down the stdin pipe
                 * for every local proc (they are all on my proct list)
                 */
                for (item = opal_list_get_first(&mca_iof_mr_hnp_component.procs);
                     item != opal_list_get_end(&mca_iof_mr_hnp_component.procs);
                     item = opal_list_get_next(item)) {
                    proct = (orte_iof_proc_t*)item;
                    if (proct->name.jobid == jdata->jobid) {
                        if (NULL == proct->sink) {
                            opal_output(0, "NULL SINK FOR PROC %s", ORTE_NAME_PRINT(&proct->name));
                            continue;
                        }
                        orte_iof_base_write_output(&proct->name, ORTE_IOF_STDIN, data, numbytes, proct->sink->wev);
                    }
                }
            } else {
                OPAL_OUTPUT_VERBOSE((1, orte_iof_base.iof_output,
                                     "%s sending %d bytes from stdout of %s to daemon %s",
                                     ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), numbytes,
                                     ORTE_NAME_PRINT(&rev->name),
                                     ORTE_NAME_PRINT(&daemon->name)));
                
                /* send the data to the daemon so it can
                 * write it to all local procs from this job
                 */
                send_data(&daemon->name, ORTE_IOF_STDIN, jdata->jobid, data, numbytes);
            }
        }
    }
    
 PROCESS:
    OPAL_OUTPUT_VERBOSE((1, orte_iof_base.iof_output,
                         "%s read %d bytes from %s of %s",
                         ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), numbytes,
                         (ORTE_IOF_STDOUT & rev->tag) ? "stdout" : ((ORTE_IOF_STDERR & rev->tag) ? "stderr" : "stddiag"),
                         ORTE_NAME_PRINT(&rev->name)));
    
    if (0 == numbytes) {
        /* if we read 0 bytes from the stdout/err/diag, find this proc
         * on our list and
         * release the appropriate event. This will delete the
         * read event and close the file descriptor
         */
        for (item = opal_list_get_first(&mca_iof_mr_hnp_component.procs);
             item != opal_list_get_end(&mca_iof_mr_hnp_component.procs);
             item = opal_list_get_next(item)) {
            proct = (orte_iof_proc_t*)item;
            mask = ORTE_NS_CMP_ALL;
            if (OPAL_EQUAL == orte_util_compare_name_fields(mask, &proct->name, &rev->name)) {
                /* found it - release corresponding event. This deletes
                 * the read event and closes the file descriptor
                 */
                if (rev->tag & ORTE_IOF_STDOUT) {
                    OBJ_RELEASE(proct->revstdout);
                } else if (rev->tag & ORTE_IOF_STDERR) {
                    OBJ_RELEASE(proct->revstderr);
                } else if (rev->tag & ORTE_IOF_STDDIAG) {
                    OBJ_RELEASE(proct->revstddiag);
                }
                /* check to see if they are all done */
                if (NULL == proct->revstdout &&
                    NULL == proct->revstderr &&
                    NULL == proct->revstddiag) {
                    /* this proc's iof is complete */
                    opal_list_remove_item(&mca_iof_mr_hnp_component.procs, item);
                    ORTE_ACTIVATE_PROC_STATE(&proct->name, ORTE_PROC_STATE_IOF_COMPLETE);
                    OBJ_RELEASE(proct);
                }
                break;
            }
        }
        return;
    } else {
        /* output this to our local output */
        if (ORTE_IOF_STDOUT & rev->tag) {
            if (write_out) {
                orte_iof_base_write_output(&rev->name, rev->tag, data, numbytes, orte_iof_base.iof_write_stdout->wev);
            }
        } else {
            orte_iof_base_write_output(&rev->name, rev->tag, data, numbytes, orte_iof_base.iof_write_stderr->wev);
        }
    }
    
    /* re-add the event */
    opal_event_add(rev->ev, 0);

    return;
}
Beispiel #30
0
int
main(int argc, char* argv[])
{
    FILE *in;
    TIFF *out = NULL;
    TIFFErrorHandler whandler = NULL;
    int compression_in = COMPRESSION_CCITTFAX3;
    int compression_out = COMPRESSION_CCITTFAX3;
    int fillorder_in = FILLORDER_LSB2MSB;
    int fillorder_out = FILLORDER_LSB2MSB;
    uint32 group3options_in = 0;	/* 1d-encoded */
    uint32 group3options_out = 0;	/* 1d-encoded */
    uint32 group4options_in = 0;	/* compressed */
    uint32 group4options_out = 0;	/* compressed */
    uint32 defrowsperstrip = (uint32) 0;
    uint32 rowsperstrip;
    int photometric_in = PHOTOMETRIC_MINISWHITE;
    int photometric_out = PHOTOMETRIC_MINISWHITE;
    int mode = FAXMODE_CLASSF;
    int rows;
    int c;
    int pn, npages;
    float resY = 196.0;
    extern int optind;
    extern char* optarg;


    while ((c = getopt(argc, argv, "R:X:o:1234ABLMPUW5678abcflmprsuvwz?")) != -1)
        switch (c) {
        /* input-related options */
        case '3':		/* input is g3-encoded */
            compression_in = COMPRESSION_CCITTFAX3;
            break;
        case '4':		/* input is g4-encoded */
            compression_in = COMPRESSION_CCITTFAX4;
            break;
        case 'U':		/* input is uncompressed (g3 and g4) */
            group3options_in |= GROUP3OPT_UNCOMPRESSED;
            group4options_in |= GROUP4OPT_UNCOMPRESSED;
            break;
        case '1':		/* input is 1d-encoded (g3 only) */
            group3options_in &= ~GROUP3OPT_2DENCODING;
            break;
        case '2':		/* input is 2d-encoded (g3 only) */
            group3options_in |= GROUP3OPT_2DENCODING;
            break;
        case 'P':	/* input has not-aligned EOL (g3 only) */
            group3options_in &= ~GROUP3OPT_FILLBITS;
            break;
        case 'A':		/* input has aligned EOL (g3 only) */
            group3options_in |= GROUP3OPT_FILLBITS;
            break;
        case 'W':		/* input has 0 mean white */
            photometric_in = PHOTOMETRIC_MINISWHITE;
            break;
        case 'B':		/* input has 0 mean black */
            photometric_in = PHOTOMETRIC_MINISBLACK;
            break;
        case 'L':		/* input has lsb-to-msb fillorder */
            fillorder_in = FILLORDER_LSB2MSB;
            break;
        case 'M':		/* input has msb-to-lsb fillorder */
            fillorder_in = FILLORDER_MSB2LSB;
            break;
        case 'R':		/* input resolution */
            resY = (float) atof(optarg);
            break;
        case 'X':		/* input width */
            xsize = (uint32) atoi(optarg);
            break;

        /* output-related options */
        case '7':		/* generate g3-encoded output */
            compression_out = COMPRESSION_CCITTFAX3;
            break;
        case '8':		/* generate g4-encoded output */
            compression_out = COMPRESSION_CCITTFAX4;
            break;
        case 'u':	/* generate uncompressed output (g3 and g4) */
            group3options_out |= GROUP3OPT_UNCOMPRESSED;
            group4options_out |= GROUP4OPT_UNCOMPRESSED;
            break;
        case '5':	/* generate 1d-encoded output (g3 only) */
            group3options_out &= ~GROUP3OPT_2DENCODING;
            break;
        case '6':	/* generate 2d-encoded output (g3 only) */
            group3options_out |= GROUP3OPT_2DENCODING;
            break;
        case 'c':		/* generate "classic" g3 format */
            mode = FAXMODE_CLASSIC;
            break;
        case 'f':		/* generate Class F format */
            mode = FAXMODE_CLASSF;
            break;
        case 'm':		/* output's fillorder is msb-to-lsb */
            fillorder_out = FILLORDER_MSB2LSB;
            break;
        case 'l':		/* output's fillorder is lsb-to-msb */
            fillorder_out = FILLORDER_LSB2MSB;
            break;
        case 'o':
            out = TIFFOpen(optarg, "w");
            if (out == NULL) {
                fprintf(stderr,
                        "%s: Can not create or open %s\n",
                        argv[0], optarg);
                return EXIT_FAILURE;
            }
            break;
        case 'a':	/* generate EOL-aligned output (g3 only) */
            group3options_out |= GROUP3OPT_FILLBITS;
            break;
        case 'p':	/* generate not EOL-aligned output (g3 only) */
            group3options_out &= ~GROUP3OPT_FILLBITS;
            break;
        case 'r':		/* rows/strip */
            defrowsperstrip = atol(optarg);
            break;
        case 's':		/* stretch image by dup'ng scanlines */
            stretch = 1;
            break;
        case 'w':		/* undocumented -- for testing */
            photometric_out = PHOTOMETRIC_MINISWHITE;
            break;
        case 'b':		/* undocumented -- for testing */
            photometric_out = PHOTOMETRIC_MINISBLACK;
            break;
        case 'z':		/* undocumented -- for testing */
            compression_out = COMPRESSION_LZW;
            break;
        case 'v':		/* -v for info */
            verbose++;
            break;
        case '?':
            usage();
            /*NOTREACHED*/
        }
    npages = argc - optind;
    if (npages < 1)
        usage();

    rowbuf = _TIFFmalloc(TIFFhowmany8(xsize));
    refbuf = _TIFFmalloc(TIFFhowmany8(xsize));
    if (rowbuf == NULL || refbuf == NULL) {
        fprintf(stderr, "%s: Not enough memory\n", argv[0]);
        return (EXIT_FAILURE);
    }

    if (out == NULL) {
        out = TIFFOpen("fax.tif", "w");
        if (out == NULL) {
            fprintf(stderr, "%s: Can not create fax.tif\n",
                    argv[0]);
            return (EXIT_FAILURE);
        }
    }

    faxTIFF = TIFFClientOpen("(FakeInput)", "w",
                             /* TIFFClientOpen() fails if we don't set existing value here */
                             TIFFClientdata(out),
                             TIFFGetReadProc(out), TIFFGetWriteProc(out),
                             TIFFGetSeekProc(out), TIFFGetCloseProc(out),
                             TIFFGetSizeProc(out), TIFFGetMapFileProc(out),
                             TIFFGetUnmapFileProc(out));
    if (faxTIFF == NULL) {
        fprintf(stderr, "%s: Can not create fake input file\n",
                argv[0]);
        return (EXIT_FAILURE);
    }
    TIFFSetMode(faxTIFF, O_RDONLY);
    TIFFSetField(faxTIFF, TIFFTAG_IMAGEWIDTH,	xsize);
    TIFFSetField(faxTIFF, TIFFTAG_SAMPLESPERPIXEL,	1);
    TIFFSetField(faxTIFF, TIFFTAG_BITSPERSAMPLE,	1);
    TIFFSetField(faxTIFF, TIFFTAG_FILLORDER,	fillorder_in);
    TIFFSetField(faxTIFF, TIFFTAG_PLANARCONFIG,	PLANARCONFIG_CONTIG);
    TIFFSetField(faxTIFF, TIFFTAG_PHOTOMETRIC,	photometric_in);
    TIFFSetField(faxTIFF, TIFFTAG_YRESOLUTION,	resY);
    TIFFSetField(faxTIFF, TIFFTAG_RESOLUTIONUNIT,	RESUNIT_INCH);

    /* NB: this must be done after directory info is setup */
    TIFFSetField(faxTIFF, TIFFTAG_COMPRESSION, compression_in);
    if (compression_in == COMPRESSION_CCITTFAX3)
        TIFFSetField(faxTIFF, TIFFTAG_GROUP3OPTIONS, group3options_in);
    else if (compression_in == COMPRESSION_CCITTFAX4)
        TIFFSetField(faxTIFF, TIFFTAG_GROUP4OPTIONS, group4options_in);
    for (pn = 0; optind < argc; pn++, optind++) {
        in = fopen(argv[optind], "r" BINMODE);
        if (in == NULL) {
            fprintf(stderr,
                    "%s: %s: Can not open\n", argv[0], argv[optind]);
            continue;
        }
#if defined(_WIN32) && defined(USE_WIN32_FILEIO)
        TIFFSetClientdata(faxTIFF, (thandle_t)_get_osfhandle(fileno(in)));
#else
        TIFFSetClientdata(faxTIFF, (thandle_t)fileno(in));
#endif
        TIFFSetFileName(faxTIFF, (const char*)argv[optind]);
        TIFFSetField(out, TIFFTAG_IMAGEWIDTH, xsize);
        TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 1);
        TIFFSetField(out, TIFFTAG_COMPRESSION, compression_out);
        TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric_out);
        TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
        TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1);
        switch (compression_out) {
        /* g3 */
        case COMPRESSION_CCITTFAX3:
            TIFFSetField(out, TIFFTAG_GROUP3OPTIONS,
                         group3options_out);
            TIFFSetField(out, TIFFTAG_FAXMODE, mode);
            rowsperstrip =
                (defrowsperstrip)?defrowsperstrip:(uint32)-1L;
            break;

        /* g4 */
        case COMPRESSION_CCITTFAX4:
            TIFFSetField(out, TIFFTAG_GROUP4OPTIONS,
                         group4options_out);
            TIFFSetField(out, TIFFTAG_FAXMODE, mode);
            rowsperstrip =
                (defrowsperstrip)?defrowsperstrip:(uint32)-1L;
            break;

        default:
            rowsperstrip = (defrowsperstrip) ?
                           defrowsperstrip : TIFFDefaultStripSize(out, 0);
        }
        TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
        TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
        TIFFSetField(out, TIFFTAG_FILLORDER, fillorder_out);
        TIFFSetField(out, TIFFTAG_SOFTWARE, "fax2tiff");
        TIFFSetField(out, TIFFTAG_XRESOLUTION, 204.0);
        if (!stretch) {
            TIFFGetField(faxTIFF, TIFFTAG_YRESOLUTION, &resY);
            TIFFSetField(out, TIFFTAG_YRESOLUTION, resY);
        } else
            TIFFSetField(out, TIFFTAG_YRESOLUTION, 196.);
        TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
        TIFFSetField(out, TIFFTAG_PAGENUMBER, pn, npages);

        if (!verbose)
            whandler = TIFFSetWarningHandler(NULL);
        rows = copyFaxFile(faxTIFF, out);
        fclose(in);
        if (!verbose)
            (void) TIFFSetWarningHandler(whandler);

        TIFFSetField(out, TIFFTAG_IMAGELENGTH, rows);

        if (verbose) {
            fprintf(stderr, "%s:\n", argv[optind]);
            fprintf(stderr, "%d rows in input\n", rows);
            fprintf(stderr, "%ld total bad rows\n",
                    (long) badfaxlines);
            fprintf(stderr, "%d max consecutive bad rows\n", badfaxrun);
        }
        if (compression_out == COMPRESSION_CCITTFAX3 &&
                mode == FAXMODE_CLASSF) {
            TIFFSetField(out, TIFFTAG_BADFAXLINES, badfaxlines);
            TIFFSetField(out, TIFFTAG_CLEANFAXDATA, badfaxlines ?
                         CLEANFAXDATA_REGENERATED : CLEANFAXDATA_CLEAN);
            TIFFSetField(out, TIFFTAG_CONSECUTIVEBADFAXLINES, badfaxrun);
        }
        TIFFWriteDirectory(out);
    }
    TIFFClose(out);
    _TIFFfree(rowbuf);
    _TIFFfree(refbuf);
    return (EXIT_SUCCESS);
}