Rizin
unix-like reverse engineering framework and cli tools
process.c File Reference
#include <assert.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <limits.h>
#include <wchar.h>
#include <malloc.h>
#include "uv.h"
#include "internal.h"
#include "handle-inl.h"
#include "req-inl.h"

Go to the source code of this file.

Classes

struct  env_var
 

Macros

#define SIGKILL   9
 
#define E_V(str)   { L##str, L##str L"=", sizeof(str) }
 

Typedefs

typedef struct env_var env_var_t
 

Functions

static void uv__init_global_job_handle (void)
 
static int uv_utf8_to_utf16_alloc (const char *s, WCHAR **ws_ptr)
 
static void uv_process_init (uv_loop_t *loop, uv_process_t *handle)
 
static WCHAR * search_path_join_test (const WCHAR *dir, size_t dir_len, const WCHAR *name, size_t name_len, const WCHAR *ext, size_t ext_len, const WCHAR *cwd, size_t cwd_len)
 
static WCHAR * path_search_walk_ext (const WCHAR *dir, size_t dir_len, const WCHAR *name, size_t name_len, WCHAR *cwd, size_t cwd_len, int name_has_ext)
 
static WCHAR * search_path (const WCHAR *file, WCHAR *cwd, const WCHAR *path)
 
WCHAR * quote_cmd_arg (const WCHAR *source, WCHAR *target)
 
int make_program_args (char **args, int verbatim_arguments, WCHAR **dst_ptr)
 
int env_strncmp (const wchar_t *a, int na, const wchar_t *b)
 
static int qsort_wcscmp (const void *a, const void *b)
 
int make_program_env (char *env_block[], WCHAR **dst_ptr)
 
static WCHAR * find_path (WCHAR *env)
 
static void CALLBACK exit_wait_callback (void *data, BOOLEAN didTimeout)
 
void uv_process_proc_exit (uv_loop_t *loop, uv_process_t *handle)
 
void uv_process_close (uv_loop_t *loop, uv_process_t *handle)
 
void uv_process_endgame (uv_loop_t *loop, uv_process_t *handle)
 
int uv_spawn (uv_loop_t *loop, uv_process_t *process, const uv_process_options_t *options)
 
static int uv__kill (HANDLE process_handle, int signum)
 
int uv_process_kill (uv_process_t *process, int signum)
 
int uv_kill (int pid, int signum)
 

Variables

static const env_var_t required_vars []
 
static HANDLE uv_global_job_handle_
 
static uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT
 

Macro Definition Documentation

◆ E_V

#define E_V (   str)    { L##str, L##str L"=", sizeof(str) }

Definition at line 46 of file process.c.

◆ SIGKILL

#define SIGKILL   9

Definition at line 37 of file process.c.

Typedef Documentation

◆ env_var_t

typedef struct env_var env_var_t

Function Documentation

◆ env_strncmp()

int env_strncmp ( const wchar_t *  a,
int  na,
const wchar_t *  b 
)

Definition at line 616 of file process.c.

616  {
617  wchar_t* a_eq;
618  wchar_t* b_eq;
619  wchar_t* A;
620  wchar_t* B;
621  int nb;
622  int r;
623 
624  if (na < 0) {
625  a_eq = wcschr(a, L'=');
626  assert(a_eq);
627  na = (int)(long)(a_eq - a);
628  } else {
629  na--;
630  }
631  b_eq = wcschr(b, L'=');
632  assert(b_eq);
633  nb = b_eq - b;
634 
635  A = alloca((na+1) * sizeof(wchar_t));
636  B = alloca((nb+1) * sizeof(wchar_t));
637 
638  r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, a, na, A, na);
639  assert(r==na);
640  A[na] = L'\0';
641  r = LCMapStringW(LOCALE_INVARIANT, LCMAP_UPPERCASE, b, nb, B, nb);
642  assert(r==nb);
643  B[nb] = L'\0';
644 
645  while (1) {
646  wchar_t AA = *A++;
647  wchar_t BB = *B++;
648  if (AA < BB) {
649  return -1;
650  } else if (AA > BB) {
651  return 1;
652  } else if (!AA && !BB) {
653  return 0;
654  }
655  }
656 }
#define A(x)
Definition: arc.h:165
#define B(x)
Definition: arc.h:166
char * alloca()
#define r
Definition: crypto_rc6.c:12
assert(limit<=UINT32_MAX/2)
static int
Definition: sfsocketcall.h:114
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
#define LOCALE_INVARIANT
Definition: win.h:44
#define L
Definition: zip_err_str.c:7

References a, A, alloca(), assert(), b, B, int, L, LOCALE_INVARIANT, and r.

Referenced by make_program_env(), and qsort_wcscmp().

◆ exit_wait_callback()

static void CALLBACK exit_wait_callback ( void *  data,
BOOLEAN  didTimeout 
)
static

Definition at line 849 of file process.c.

849  {
850  uv_process_t* process = (uv_process_t*) data;
851  uv_loop_t* loop = process->loop;
852 
853  assert(didTimeout == FALSE);
854  assert(process);
855  assert(!process->exit_cb_pending);
856 
857  process->exit_cb_pending = 1;
858 
859  /* Post completed */
860  POST_COMPLETION_FOR_REQ(loop, &process->exit_req);
861 }
#define FALSE
Definition: mybfd.h:102
#define POST_COMPLETION_FOR_REQ(loop, req)
Definition: req-inl.h:76
Definition: uv.h:1780
uv_loop_t * loop
Definition: main.c:7
static zip_compression_status_t process(void *ud, zip_uint8_t *data, zip_uint64_t *length)

References assert(), FALSE, loop, POST_COMPLETION_FOR_REQ, and process().

Referenced by uv_spawn().

◆ find_path()

static WCHAR* find_path ( WCHAR *  env)
static

Definition at line 831 of file process.c.

831  {
832  for (; env != NULL && *env != 0; env += wcslen(env) + 1) {
833  if ((env[0] == L'P' || env[0] == L'p') &&
834  (env[1] == L'A' || env[1] == L'a') &&
835  (env[2] == L'T' || env[2] == L't') &&
836  (env[3] == L'H' || env[3] == L'h') &&
837  (env[4] == L'=')) {
838  return &env[5];
839  }
840  }
841 
842  return NULL;
843 }
#define NULL
Definition: cris-opc.c:27
static char ** env
Definition: sys.c:32

References env, L, and NULL.

Referenced by fs__opendir(), uv_exepath(), and uv_spawn().

◆ make_program_args()

int make_program_args ( char **  args,
int  verbatim_arguments,
WCHAR **  dst_ptr 
)

Definition at line 526 of file process.c.

526  {
527  char** arg;
528  WCHAR* dst = NULL;
529  WCHAR* temp_buffer = NULL;
530  size_t dst_len = 0;
531  size_t temp_buffer_len = 0;
532  WCHAR* pos;
533  int arg_count = 0;
534  int err = 0;
535 
536  /* Count the required size. */
537  for (arg = args; *arg; arg++) {
538  DWORD arg_len;
539 
540  arg_len = MultiByteToWideChar(CP_UTF8,
541  0,
542  *arg,
543  -1,
544  NULL,
545  0);
546  if (arg_len == 0) {
547  return GetLastError();
548  }
549 
550  dst_len += arg_len;
551 
552  if (arg_len > temp_buffer_len)
553  temp_buffer_len = arg_len;
554 
555  arg_count++;
556  }
557 
558  /* Adjust for potential quotes. Also assume the worst-case scenario that
559  * every character needs escaping, so we need twice as much space. */
560  dst_len = dst_len * 2 + arg_count * 2;
561 
562  /* Allocate buffer for the final command line. */
563  dst = (WCHAR*) uv__malloc(dst_len * sizeof(WCHAR));
564  if (dst == NULL) {
565  err = ERROR_OUTOFMEMORY;
566  goto error;
567  }
568 
569  /* Allocate temporary working buffer. */
570  temp_buffer = (WCHAR*) uv__malloc(temp_buffer_len * sizeof(WCHAR));
571  if (temp_buffer == NULL) {
572  err = ERROR_OUTOFMEMORY;
573  goto error;
574  }
575 
576  pos = dst;
577  for (arg = args; *arg; arg++) {
578  DWORD arg_len;
579 
580  /* Convert argument to wide char. */
581  arg_len = MultiByteToWideChar(CP_UTF8,
582  0,
583  *arg,
584  -1,
585  temp_buffer,
586  (int) (dst + dst_len - pos));
587  if (arg_len == 0) {
588  err = GetLastError();
589  goto error;
590  }
591 
592  if (verbatim_arguments) {
593  /* Copy verbatim. */
594  wcscpy(pos, temp_buffer);
595  pos += arg_len - 1;
596  } else {
597  /* Quote/escape, if needed. */
598  pos = quote_cmd_arg(temp_buffer, pos);
599  }
600 
601  *pos++ = *(arg + 1) ? L' ' : L'\0';
602  }
603 
604  uv__free(temp_buffer);
605 
606  *dst_ptr = dst;
607  return 0;
608 
609 error:
610  uv__free(dst);
611  uv__free(temp_buffer);
612  return err;
613 }
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
static bool err
Definition: armass.c:435
char * dst
Definition: lz4.h:724
int args
Definition: mipsasm.c:18
int pos
Definition: main.c:11
void error(const char *msg)
Definition: untgz.c:593
void * uv__malloc(size_t size)
Definition: uv-common.c:75
void uv__free(void *ptr)
Definition: uv-common.c:81
WCHAR * quote_cmd_arg(const WCHAR *source, WCHAR *target)
Definition: process.c:453
DWORD

References arg(), args, dst, DWORD, err, error(), L, NULL, pos, quote_cmd_arg(), uv__free(), and uv__malloc().

Referenced by uv_spawn().

◆ make_program_env()

int make_program_env ( char *  env_block[],
WCHAR **  dst_ptr 
)

Definition at line 682 of file process.c.

682  {
683  WCHAR* dst;
684  WCHAR* ptr;
685  char** env;
686  size_t env_len = 0;
687  int len;
688  size_t i;
689  DWORD var_size;
690  size_t env_block_count = 1; /* 1 for null-terminator */
691  WCHAR* dst_copy;
692  WCHAR** ptr_copy;
693  WCHAR** env_copy;
694  DWORD required_vars_value_len[ARRAY_SIZE(required_vars)];
695 
696  /* first pass: determine size in UTF-16 */
697  for (env = env_block; *env; env++) {
698  int len;
699  if (strchr(*env, '=')) {
700  len = MultiByteToWideChar(CP_UTF8,
701  0,
702  *env,
703  -1,
704  NULL,
705  0);
706  if (len <= 0) {
707  return GetLastError();
708  }
709  env_len += len;
710  env_block_count++;
711  }
712  }
713 
714  /* second pass: copy to UTF-16 environment block */
715  dst_copy = (WCHAR*)uv__malloc(env_len * sizeof(WCHAR));
716  if (dst_copy == NULL && env_len > 0) {
717  return ERROR_OUTOFMEMORY;
718  }
719  env_copy = alloca(env_block_count * sizeof(WCHAR*));
720 
721  ptr = dst_copy;
722  ptr_copy = env_copy;
723  for (env = env_block; *env; env++) {
724  if (strchr(*env, '=')) {
725  len = MultiByteToWideChar(CP_UTF8,
726  0,
727  *env,
728  -1,
729  ptr,
730  (int) (env_len - (ptr - dst_copy)));
731  if (len <= 0) {
732  DWORD err = GetLastError();
733  uv__free(dst_copy);
734  return err;
735  }
736  *ptr_copy++ = ptr;
737  ptr += len;
738  }
739  }
740  *ptr_copy = NULL;
741  assert(env_len == 0 || env_len == (size_t) (ptr - dst_copy));
742 
743  /* sort our (UTF-16) copy */
744  qsort(env_copy, env_block_count-1, sizeof(wchar_t*), qsort_wcscmp);
745 
746  /* third pass: check for required variables */
747  for (ptr_copy = env_copy, i = 0; i < ARRAY_SIZE(required_vars); ) {
748  int cmp;
749  if (!*ptr_copy) {
750  cmp = -1;
751  } else {
752  cmp = env_strncmp(required_vars[i].wide_eq,
754  *ptr_copy);
755  }
756  if (cmp < 0) {
757  /* missing required var */
758  var_size = GetEnvironmentVariableW(required_vars[i].wide, NULL, 0);
759  required_vars_value_len[i] = var_size;
760  if (var_size != 0) {
761  env_len += required_vars[i].len;
762  env_len += var_size;
763  }
764  i++;
765  } else {
766  ptr_copy++;
767  if (cmp == 0)
768  i++;
769  }
770  }
771 
772  /* final pass: copy, in sort order, and inserting required variables */
773  dst = uv__malloc((1+env_len) * sizeof(WCHAR));
774  if (!dst) {
775  uv__free(dst_copy);
776  return ERROR_OUTOFMEMORY;
777  }
778 
779  for (ptr = dst, ptr_copy = env_copy, i = 0;
780  *ptr_copy || i < ARRAY_SIZE(required_vars);
781  ptr += len) {
782  int cmp;
783  if (i >= ARRAY_SIZE(required_vars)) {
784  cmp = 1;
785  } else if (!*ptr_copy) {
786  cmp = -1;
787  } else {
788  cmp = env_strncmp(required_vars[i].wide_eq,
790  *ptr_copy);
791  }
792  if (cmp < 0) {
793  /* missing required var */
794  len = required_vars_value_len[i];
795  if (len) {
796  wcscpy(ptr, required_vars[i].wide_eq);
797  ptr += required_vars[i].len;
798  var_size = GetEnvironmentVariableW(required_vars[i].wide,
799  ptr,
800  (int) (env_len - (ptr - dst)));
801  if (var_size != (DWORD) (len - 1)) { /* TODO: handle race condition? */
802  uv_fatal_error(GetLastError(), "GetEnvironmentVariableW");
803  }
804  }
805  i++;
806  } else {
807  /* copy var from env_block */
808  len = wcslen(*ptr_copy) + 1;
809  wmemcpy(ptr, *ptr_copy, len);
810  ptr_copy++;
811  if (cmp == 0)
812  i++;
813  }
814  }
815 
816  /* Terminate with an extra NULL. */
817  assert(env_len == (size_t) (ptr - dst));
818  *ptr = L'\0';
819 
820  uv__free(dst_copy);
821  *dst_ptr = dst;
822  return 0;
823 }
size_t len
Definition: 6502dis.c:15
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
static RzILOpEffect * cmp(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:942
void uv_fatal_error(const int errorno, const char *syscall)
Definition: error.c:35
void qsort(void *a, size_t n, size_t es, int(*cmp)(const void *, const void *))
Definition: qsort.h:130
const size_t len
Definition: process.c:43
static int qsort_wcscmp(const void *a, const void *b)
Definition: process.c:659
int env_strncmp(const wchar_t *a, int na, const wchar_t *b)
Definition: process.c:616
static const env_var_t required_vars[]
Definition: process.c:48

References alloca(), ARRAY_SIZE, assert(), cmp(), dst, DWORD, env, env_strncmp(), err, i, L, len, env_var::len, NULL, qsort(), qsort_wcscmp(), required_vars, uv__free(), uv__malloc(), and uv_fatal_error().

Referenced by uv_spawn().

◆ path_search_walk_ext()

static WCHAR* path_search_walk_ext ( const WCHAR *  dir,
size_t  dir_len,
const WCHAR *  name,
size_t  name_len,
WCHAR *  cwd,
size_t  cwd_len,
int  name_has_ext 
)
static

Definition at line 255 of file process.c.

261  {
262  WCHAR* result;
263 
264  /* If the name itself has a nonempty extension, try this extension first */
265  if (name_has_ext) {
266  result = search_path_join_test(dir, dir_len,
267  name, name_len,
268  L"", 0,
269  cwd, cwd_len);
270  if (result != NULL) {
271  return result;
272  }
273  }
274 
275  /* Try .com extension */
276  result = search_path_join_test(dir, dir_len,
277  name, name_len,
278  L"com", 3,
279  cwd, cwd_len);
280  if (result != NULL) {
281  return result;
282  }
283 
284  /* Try .exe extension */
285  result = search_path_join_test(dir, dir_len,
286  name, name_len,
287  L"exe", 3,
288  cwd, cwd_len);
289  if (result != NULL) {
290  return result;
291  }
292 
293  return NULL;
294 }
Definition: z80asm.h:102
static WCHAR * search_path_join_test(const WCHAR *dir, size_t dir_len, const WCHAR *name, size_t name_len, const WCHAR *ext, size_t ext_len, const WCHAR *cwd, size_t cwd_len)
Definition: process.c:162

References test-lz4-speed::cwd, L, NULL, and search_path_join_test().

Referenced by search_path().

◆ qsort_wcscmp()

static int qsort_wcscmp ( const void *  a,
const void *  b 
)
static

Definition at line 659 of file process.c.

659  {
660  wchar_t* astr = *(wchar_t* const*)a;
661  wchar_t* bstr = *(wchar_t* const*)b;
662  return env_strncmp(astr, -1, bstr);
663 }

References a, b, and env_strncmp().

Referenced by make_program_env().

◆ quote_cmd_arg()

WCHAR* quote_cmd_arg ( const WCHAR *  source,
WCHAR *  target 
)

Definition at line 453 of file process.c.

453  {
454  size_t len = wcslen(source);
455  size_t i;
456  int quote_hit;
457  WCHAR* start;
458 
459  if (len == 0) {
460  /* Need double quotation for empty argument */
461  *(target++) = L'"';
462  *(target++) = L'"';
463  return target;
464  }
465 
466  if (NULL == wcspbrk(source, L" \t\"")) {
467  /* No quotation needed */
468  wcsncpy(target, source, len);
469  target += len;
470  return target;
471  }
472 
473  if (NULL == wcspbrk(source, L"\"\\")) {
474  /*
475  * No embedded double quotes or backlashes, so I can just wrap
476  * quote marks around the whole thing.
477  */
478  *(target++) = L'"';
479  wcsncpy(target, source, len);
480  target += len;
481  *(target++) = L'"';
482  return target;
483  }
484 
485  /*
486  * Expected input/output:
487  * input : hello"world
488  * output: "hello\"world"
489  * input : hello""world
490  * output: "hello\"\"world"
491  * input : hello\world
492  * output: hello\world
493  * input : hello\\world
494  * output: hello\\world
495  * input : hello\"world
496  * output: "hello\\\"world"
497  * input : hello\\"world
498  * output: "hello\\\\\"world"
499  * input : hello world\
500  * output: "hello world\\"
501  */
502 
503  *(target++) = L'"';
504  start = target;
505  quote_hit = 1;
506 
507  for (i = len; i > 0; --i) {
508  *(target++) = source[i - 1];
509 
510  if (quote_hit && source[i - 1] == L'\\') {
511  *(target++) = L'\\';
512  } else if(source[i - 1] == L'"') {
513  quote_hit = 1;
514  *(target++) = L'\\';
515  } else {
516  quote_hit = 0;
517  }
518  }
519  target[0] = L'\0';
520  wcsrev(start);
521  *(target++) = L'"';
522  return target;
523 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
const char * source
Definition: lz4.h:699

References i, L, len, NULL, source, and start.

Referenced by make_program_args().

◆ search_path()

static WCHAR* search_path ( const WCHAR *  file,
WCHAR *  cwd,
const WCHAR *  path 
)
static

Definition at line 340 of file process.c.

342  {
343  int file_has_dir;
344  WCHAR* result = NULL;
345  WCHAR *file_name_start;
346  WCHAR *dot;
347  const WCHAR *dir_start, *dir_end, *dir_path;
348  size_t dir_len;
349  int name_has_ext;
350 
351  size_t file_len = wcslen(file);
352  size_t cwd_len = wcslen(cwd);
353 
354  /* If the caller supplies an empty filename,
355  * we're not gonna return c:\windows\.exe -- GFY!
356  */
357  if (file_len == 0
358  || (file_len == 1 && file[0] == L'.')) {
359  return NULL;
360  }
361 
362  /* Find the start of the filename so we can split the directory from the
363  * name. */
364  for (file_name_start = (WCHAR*)file + file_len;
365  file_name_start > file
366  && file_name_start[-1] != L'\\'
367  && file_name_start[-1] != L'/'
368  && file_name_start[-1] != L':';
369  file_name_start--);
370 
371  file_has_dir = file_name_start != file;
372 
373  /* Check if the filename includes an extension */
374  dot = wcschr(file_name_start, L'.');
375  name_has_ext = (dot != NULL && dot[1] != L'\0');
376 
377  if (file_has_dir) {
378  /* The file has a path inside, don't use path */
379  result = path_search_walk_ext(
380  file, file_name_start - file,
381  file_name_start, file_len - (file_name_start - file),
382  cwd, cwd_len,
383  name_has_ext);
384 
385  } else {
386  dir_end = path;
387 
388  /* The file is really only a name; look in cwd first, then scan path */
389  result = path_search_walk_ext(L"", 0,
390  file, file_len,
391  cwd, cwd_len,
392  name_has_ext);
393 
394  while (result == NULL) {
395  if (*dir_end == L'\0') {
396  break;
397  }
398 
399  /* Skip the separator that dir_end now points to */
400  if (dir_end != path || *path == L';') {
401  dir_end++;
402  }
403 
404  /* Next slice starts just after where the previous one ended */
405  dir_start = dir_end;
406 
407  /* If path is quoted, find quote end */
408  if (*dir_start == L'"' || *dir_start == L'\'') {
409  dir_end = wcschr(dir_start + 1, *dir_start);
410  if (dir_end == NULL) {
411  dir_end = wcschr(dir_start, L'\0');
412  }
413  }
414  /* Slice until the next ; or \0 is found */
415  dir_end = wcschr(dir_end, L';');
416  if (dir_end == NULL) {
417  dir_end = wcschr(dir_start, L'\0');
418  }
419 
420  /* If the slice is zero-length, don't bother */
421  if (dir_end - dir_start == 0) {
422  continue;
423  }
424 
425  dir_path = dir_start;
426  dir_len = dir_end - dir_start;
427 
428  /* Adjust if the path is quoted. */
429  if (dir_path[0] == '"' || dir_path[0] == '\'') {
430  ++dir_path;
431  --dir_len;
432  }
433 
434  if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') {
435  --dir_len;
436  }
437 
438  result = path_search_walk_ext(dir_path, dir_len,
439  file, file_len,
440  cwd, cwd_len,
441  name_has_ext);
442  }
443  }
444 
445  return result;
446 }
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35
Definition: gzappend.c:170
static WCHAR * path_search_walk_ext(const WCHAR *dir, size_t dir_len, const WCHAR *name, size_t name_len, WCHAR *cwd, size_t cwd_len, int name_has_ext)
Definition: process.c:255
static int file
Definition: z80asm.c:58

References test-lz4-speed::cwd, file, L, NULL, path, and path_search_walk_ext().

Referenced by uv_spawn().

◆ search_path_join_test()

static WCHAR* search_path_join_test ( const WCHAR *  dir,
size_t  dir_len,
const WCHAR *  name,
size_t  name_len,
const WCHAR *  ext,
size_t  ext_len,
const WCHAR *  cwd,
size_t  cwd_len 
)
static

Definition at line 162 of file process.c.

169  {
170  WCHAR *result, *result_pos;
171  DWORD attrs;
172  if (dir_len > 2 && dir[0] == L'\\' && dir[1] == L'\\') {
173  /* It's a UNC path so ignore cwd */
174  cwd_len = 0;
175  } else if (dir_len >= 1 && (dir[0] == L'/' || dir[0] == L'\\')) {
176  /* It's a full path without drive letter, use cwd's drive letter only */
177  cwd_len = 2;
178  } else if (dir_len >= 2 && dir[1] == L':' &&
179  (dir_len < 3 || (dir[2] != L'/' && dir[2] != L'\\'))) {
180  /* It's a relative path with drive letter (ext.g. D:../some/file)
181  * Replace drive letter in dir by full cwd if it points to the same drive,
182  * otherwise use the dir only.
183  */
184  if (cwd_len < 2 || _wcsnicmp(cwd, dir, 2) != 0) {
185  cwd_len = 0;
186  } else {
187  dir += 2;
188  dir_len -= 2;
189  }
190  } else if (dir_len > 2 && dir[1] == L':') {
191  /* It's an absolute path with drive letter
192  * Don't use the cwd at all
193  */
194  cwd_len = 0;
195  }
196 
197  /* Allocate buffer for output */
198  result = result_pos = (WCHAR*)uv__malloc(sizeof(WCHAR) *
199  (cwd_len + 1 + dir_len + 1 + name_len + 1 + ext_len + 1));
200 
201  /* Copy cwd */
202  wcsncpy(result_pos, cwd, cwd_len);
203  result_pos += cwd_len;
204 
205  /* Add a path separator if cwd didn't end with one */
206  if (cwd_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {
207  result_pos[0] = L'\\';
208  result_pos++;
209  }
210 
211  /* Copy dir */
212  wcsncpy(result_pos, dir, dir_len);
213  result_pos += dir_len;
214 
215  /* Add a separator if the dir didn't end with one */
216  if (dir_len && wcsrchr(L"\\/:", result_pos[-1]) == NULL) {
217  result_pos[0] = L'\\';
218  result_pos++;
219  }
220 
221  /* Copy filename */
222  wcsncpy(result_pos, name, name_len);
223  result_pos += name_len;
224 
225  if (ext_len) {
226  /* Add a dot if the filename didn't end with one */
227  if (name_len && result_pos[-1] != '.') {
228  result_pos[0] = L'.';
229  result_pos++;
230  }
231 
232  /* Copy extension */
233  wcsncpy(result_pos, ext, ext_len);
234  result_pos += ext_len;
235  }
236 
237  /* Null terminator */
238  result_pos[0] = L'\0';
239 
240  attrs = GetFileAttributesW(result);
241 
242  if (attrs != INVALID_FILE_ATTRIBUTES &&
243  !(attrs & FILE_ATTRIBUTE_DIRECTORY)) {
244  return result;
245  }
246 
247  uv__free(result);
248  return NULL;
249 }
static const char ext[]
Definition: apprentice.c:1981

References test-lz4-speed::cwd, DWORD, ext, L, NULL, uv__free(), and uv__malloc().

Referenced by path_search_walk_ext().

◆ uv__init_global_job_handle()

static void uv__init_global_job_handle ( void  )
static

Definition at line 67 of file process.c.

67  {
68  /* Create a job object and set it up to kill all contained processes when
69  * it's closed. Since this handle is made non-inheritable and we're not
70  * giving it to anyone, we're the only process holding a reference to it.
71  * That means that if this process exits it is closed and all the processes
72  * it contains are killed. All processes created with uv_spawn that are not
73  * spawned with the UV_PROCESS_DETACHED flag are assigned to this job.
74  *
75  * We're setting the JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag so only the
76  * processes that we explicitly add are affected, and *their* subprocesses
77  * are not. This ensures that our child processes are not limited in their
78  * ability to use job control on Windows versions that don't deal with
79  * nested jobs (prior to Windows 8 / Server 2012). It also lets our child
80  * processes created detached processes without explicitly breaking away
81  * from job control (which uv_spawn doesn't, either).
82  */
83  SECURITY_ATTRIBUTES attr;
84  JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
85 
86  memset(&attr, 0, sizeof attr);
87  attr.bInheritHandle = FALSE;
88 
89  memset(&info, 0, sizeof info);
90  info.BasicLimitInformation.LimitFlags =
95 
96  uv_global_job_handle_ = CreateJobObjectW(&attr, NULL);
98  uv_fatal_error(GetLastError(), "CreateJobObjectW");
99 
100  if (!SetInformationJobObject(uv_global_job_handle_,
101  JobObjectExtendedLimitInformation,
102  &info,
103  sizeof info))
104  uv_fatal_error(GetLastError(), "SetInformationJobObject");
105 }
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
return memset(p, 0, total)
static HANDLE uv_global_job_handle_
Definition: process.c:63
#define JOB_OBJECT_LIMIT_BREAKAWAY_OK
Definition: winapi.h:4098
#define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
Definition: winapi.h:4104
#define JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
Definition: winapi.h:4095
#define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK
Definition: winapi.h:4101

References FALSE, info(), JOB_OBJECT_LIMIT_BREAKAWAY_OK, JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION, JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK, memset(), NULL, uv_fatal_error(), and uv_global_job_handle_.

Referenced by uv_spawn().

◆ uv__kill()

static int uv__kill ( HANDLE  process_handle,
int  signum 
)
static

Definition at line 1189 of file process.c.

1189  {
1190  if (signum < 0 || signum >= NSIG) {
1191  return UV_EINVAL;
1192  }
1193 
1194  switch (signum) {
1195  case SIGTERM:
1196  case SIGKILL:
1197  case SIGINT: {
1198  /* Unconditionally terminate the process. On Windows, killed processes
1199  * normally return 1. */
1200  DWORD status;
1201  int err;
1202 
1203  if (TerminateProcess(process_handle, 1))
1204  return 0;
1205 
1206  /* If the process already exited before TerminateProcess was called,.
1207  * TerminateProcess will fail with ERROR_ACCESS_DENIED. */
1208  err = GetLastError();
1209  if (err == ERROR_ACCESS_DENIED &&
1210  GetExitCodeProcess(process_handle, &status) &&
1211  status != STILL_ACTIVE) {
1212  return UV_ESRCH;
1213  }
1214 
1215  return uv_translate_sys_error(err);
1216  }
1217 
1218  case 0: {
1219  /* Health check: is the process still alive? */
1220  DWORD status;
1221 
1222  if (!GetExitCodeProcess(process_handle, &status))
1223  return uv_translate_sys_error(GetLastError());
1224 
1225  if (status != STILL_ACTIVE)
1226  return UV_ESRCH;
1227 
1228  return 0;
1229  }
1230 
1231  default:
1232  /* Unsupported signal. */
1233  return UV_ENOSYS;
1234  }
1235 }
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment signum
Definition: sflib.h:79
UV_EXTERN int uv_translate_sys_error(int sys_errno)
Definition: core.c:1249
#define SIGKILL
Definition: process.c:37
#define NSIG
Definition: win.h:95

References DWORD, err, NSIG, SIGKILL, signum, status, and uv_translate_sys_error().

Referenced by uv_kill(), and uv_process_kill().

◆ uv_kill()

int uv_kill ( int  pid,
int  signum 
)

Definition at line 1256 of file process.c.

1256  {
1257  int err;
1258  HANDLE process_handle;
1259 
1260  if (pid == 0) {
1261  process_handle = GetCurrentProcess();
1262  } else {
1263  process_handle = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION,
1264  FALSE,
1265  pid);
1266  }
1267 
1268  if (process_handle == NULL) {
1269  err = GetLastError();
1270  if (err == ERROR_INVALID_PARAMETER) {
1271  return UV_ESRCH;
1272  } else {
1273  return uv_translate_sys_error(err);
1274  }
1275  }
1276 
1277  err = uv__kill(process_handle, signum);
1278  CloseHandle(process_handle);
1279 
1280  return err; /* err is already translated. */
1281 }
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
Definition: sflib.h:64
static int uv__kill(HANDLE process_handle, int signum)
Definition: process.c:1189
DWORD * HANDLE

References err, FALSE, HANDLE, kill, NULL, pid, signum, UV__ERR, uv__kill(), and uv_translate_sys_error().

◆ uv_process_close()

void uv_process_close ( uv_loop_t loop,
uv_process_t handle 
)

Definition at line 903 of file process.c.

903  {
905 
906  if (handle->wait_handle != INVALID_HANDLE_VALUE) {
907  /* This blocks until either the wait was cancelled, or the callback has
908  * completed. */
909  BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE);
910  if (!r) {
911  /* This should never happen, and if it happens, we can't recover... */
912  uv_fatal_error(GetLastError(), "UnregisterWaitEx");
913  }
914 
915  handle->wait_handle = INVALID_HANDLE_VALUE;
916  }
917 
918  if (!handle->exit_cb_pending) {
920  }
921 }
static mcore_handle handle
Definition: asm_mcore.c:8
static INLINE void uv_want_endgame(uv_loop_t *loop, uv_handle_t *handle)
Definition: handle-inl.h:88
#define uv__handle_closing(handle)
Definition: handle-inl.h:63
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21

References handle, INVALID_HANDLE_VALUE, loop, r, uv__handle_closing, uv_fatal_error(), and uv_want_endgame().

Referenced by uv_close().

◆ uv_process_endgame()

void uv_process_endgame ( uv_loop_t loop,
uv_process_t handle 
)

Definition at line 924 of file process.c.

924  {
925  assert(!handle->exit_cb_pending);
926  assert(handle->flags & UV_HANDLE_CLOSING);
927  assert(!(handle->flags & UV_HANDLE_CLOSED));
928 
929  /* Clean-up the process handle. */
930  CloseHandle(handle->process_handle);
931 
933 }
#define uv__handle_close(handle)
Definition: handle-inl.h:76
@ UV_HANDLE_CLOSING
Definition: uv-common.h:74
@ UV_HANDLE_CLOSED
Definition: uv-common.h:75

References assert(), handle, uv__handle_close, UV_HANDLE_CLOSED, and UV_HANDLE_CLOSING.

Referenced by uv_process_endgames().

◆ uv_process_init()

static void uv_process_init ( uv_loop_t loop,
uv_process_t handle 
)
static

Definition at line 140 of file process.c.

140  {
141  uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS);
142  handle->exit_cb = NULL;
143  handle->pid = 0;
144  handle->exit_signal = 0;
145  handle->wait_handle = INVALID_HANDLE_VALUE;
146  handle->process_handle = INVALID_HANDLE_VALUE;
147  handle->child_stdio_buffer = NULL;
148  handle->exit_cb_pending = 0;
149 
150  UV_REQ_INIT(&handle->exit_req, UV_PROCESS_EXIT);
151  handle->exit_req.data = handle;
152 }
#define UV_REQ_INIT(req, typ)
Definition: uv-common.h:322
#define uv__handle_init(loop_, h, type_)
Definition: uv-common.h:301

References handle, INVALID_HANDLE_VALUE, loop, NULL, uv__handle_init, and UV_REQ_INIT.

Referenced by uv_spawn().

◆ uv_process_kill()

int uv_process_kill ( uv_process_t process,
int  signum 
)

Definition at line 1238 of file process.c.

1238  {
1239  int err;
1240 
1241  if (process->process_handle == INVALID_HANDLE_VALUE) {
1242  return UV_EINVAL;
1243  }
1244 
1245  err = uv__kill(process->process_handle, signum);
1246  if (err) {
1247  return err; /* err is already translated. */
1248  }
1249 
1250  process->exit_signal = signum;
1251 
1252  return 0;
1253 }

References err, INVALID_HANDLE_VALUE, process(), signum, uv__kill(), and uv_kill().

◆ uv_process_proc_exit()

void uv_process_proc_exit ( uv_loop_t loop,
uv_process_t handle 
)

Definition at line 865 of file process.c.

865  {
866  int64_t exit_code;
867  DWORD status;
868 
869  assert(handle->exit_cb_pending);
870  handle->exit_cb_pending = 0;
871 
872  /* If we're closing, don't call the exit callback. Just schedule a close
873  * callback now. */
874  if (handle->flags & UV_HANDLE_CLOSING) {
876  return;
877  }
878 
879  /* Unregister from process notification. */
880  if (handle->wait_handle != INVALID_HANDLE_VALUE) {
881  UnregisterWait(handle->wait_handle);
882  handle->wait_handle = INVALID_HANDLE_VALUE;
883  }
884 
885  /* Set the handle to inactive: no callbacks will be made after the exit
886  * callback. */
888 
889  if (GetExitCodeProcess(handle->process_handle, &status)) {
890  exit_code = status;
891  } else {
892  /* Unable to obtain the exit code. This should never happen. */
893  exit_code = uv_translate_sys_error(GetLastError());
894  }
895 
896  /* Fire the exit callback. */
897  if (handle->exit_cb) {
898  handle->exit_cb(handle, exit_code, handle->exit_signal);
899  }
900 }
long int64_t
Definition: sftypes.h:32
#define uv__handle_stop(h)
Definition: uv-common.h:266

References assert(), DWORD, handle, INVALID_HANDLE_VALUE, loop, status, uv__handle_stop, UV_HANDLE_CLOSING, uv_translate_sys_error(), and uv_want_endgame().

Referenced by uv_process_reqs().

◆ uv_spawn()

int uv_spawn ( uv_loop_t loop,
uv_process_t process,
const uv_process_options_t options 
)

Definition at line 936 of file process.c.

938  {
939  int i;
940  int err = 0;
941  WCHAR* path = NULL, *alloc_path = NULL;
942  BOOL result;
943  WCHAR* application_path = NULL, *application = NULL, *arguments = NULL,
944  *env = NULL, *cwd = NULL;
945  STARTUPINFOW startup;
946  PROCESS_INFORMATION info;
947  DWORD process_flags;
948 
950  process->exit_cb = options->exit_cb;
951 
952  if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
953  return UV_ENOTSUP;
954  }
955 
956  if (options->file == NULL ||
957  options->args == NULL) {
958  return UV_EINVAL;
959  }
960 
961  assert(options->file != NULL);
962  assert(!(options->flags & ~(UV_PROCESS_DETACHED |
969 
970  err = uv_utf8_to_utf16_alloc(options->file, &application);
971  if (err)
972  goto done;
973 
975  options->args,
977  &arguments);
978  if (err)
979  goto done;
980 
981  if (options->env) {
982  err = make_program_env(options->env, &env);
983  if (err)
984  goto done;
985  }
986 
987  if (options->cwd) {
988  /* Explicit cwd */
990  if (err)
991  goto done;
992 
993  } else {
994  /* Inherit cwd */
995  DWORD cwd_len, r;
996 
997  cwd_len = GetCurrentDirectoryW(0, NULL);
998  if (!cwd_len) {
999  err = GetLastError();
1000  goto done;
1001  }
1002 
1003  cwd = (WCHAR*) uv__malloc(cwd_len * sizeof(WCHAR));
1004  if (cwd == NULL) {
1005  err = ERROR_OUTOFMEMORY;
1006  goto done;
1007  }
1008 
1009  r = GetCurrentDirectoryW(cwd_len, cwd);
1010  if (r == 0 || r >= cwd_len) {
1011  err = GetLastError();
1012  goto done;
1013  }
1014  }
1015 
1016  /* Get PATH environment variable. */
1017  path = find_path(env);
1018  if (path == NULL) {
1019  DWORD path_len, r;
1020 
1021  path_len = GetEnvironmentVariableW(L"PATH", NULL, 0);
1022  if (path_len == 0) {
1023  err = GetLastError();
1024  goto done;
1025  }
1026 
1027  alloc_path = (WCHAR*) uv__malloc(path_len * sizeof(WCHAR));
1028  if (alloc_path == NULL) {
1029  err = ERROR_OUTOFMEMORY;
1030  goto done;
1031  }
1032  path = alloc_path;
1033 
1034  r = GetEnvironmentVariableW(L"PATH", path, path_len);
1035  if (r == 0 || r >= path_len) {
1036  err = GetLastError();
1037  goto done;
1038  }
1039  }
1040 
1041  err = uv__stdio_create(loop, options, &process->child_stdio_buffer);
1042  if (err)
1043  goto done;
1044 
1045  application_path = search_path(application,
1046  cwd,
1047  path);
1048  if (application_path == NULL) {
1049  /* Not found. */
1050  err = ERROR_FILE_NOT_FOUND;
1051  goto done;
1052  }
1053 
1054  startup.cb = sizeof(startup);
1055  startup.lpReserved = NULL;
1056  startup.lpDesktop = NULL;
1057  startup.lpTitle = NULL;
1058  startup.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
1059 
1060  startup.cbReserved2 = uv__stdio_size(process->child_stdio_buffer);
1061  startup.lpReserved2 = (BYTE*) process->child_stdio_buffer;
1062 
1063  startup.hStdInput = uv__stdio_handle(process->child_stdio_buffer, 0);
1064  startup.hStdOutput = uv__stdio_handle(process->child_stdio_buffer, 1);
1065  startup.hStdError = uv__stdio_handle(process->child_stdio_buffer, 2);
1066 
1067  process_flags = CREATE_UNICODE_ENVIRONMENT;
1068 
1069  if ((options->flags & UV_PROCESS_WINDOWS_HIDE_CONSOLE) ||
1070  (options->flags & UV_PROCESS_WINDOWS_HIDE)) {
1071  /* Avoid creating console window if stdio is not inherited. */
1072  for (i = 0; i < options->stdio_count; i++) {
1073  if (options->stdio[i].flags & UV_INHERIT_FD)
1074  break;
1075  if (i == options->stdio_count - 1)
1076  process_flags |= CREATE_NO_WINDOW;
1077  }
1078  }
1079  if ((options->flags & UV_PROCESS_WINDOWS_HIDE_GUI) ||
1080  (options->flags & UV_PROCESS_WINDOWS_HIDE)) {
1081  /* Use SW_HIDE to avoid any potential process window. */
1082  startup.wShowWindow = SW_HIDE;
1083  } else {
1084  startup.wShowWindow = SW_SHOWDEFAULT;
1085  }
1086 
1087  if (options->flags & UV_PROCESS_DETACHED) {
1088  /* Note that we're not setting the CREATE_BREAKAWAY_FROM_JOB flag. That
1089  * means that libuv might not let you create a fully daemonized process
1090  * when run under job control. However the type of job control that libuv
1091  * itself creates doesn't trickle down to subprocesses so they can still
1092  * daemonize.
1093  *
1094  * A reason to not do this is that CREATE_BREAKAWAY_FROM_JOB makes the
1095  * CreateProcess call fail if we're under job control that doesn't allow
1096  * breakaway.
1097  */
1098  process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
1099  }
1100 
1101  if (!CreateProcessW(application_path,
1102  arguments,
1103  NULL,
1104  NULL,
1105  1,
1106  process_flags,
1107  env,
1108  cwd,
1109  &startup,
1110  &info)) {
1111  /* CreateProcessW failed. */
1112  err = GetLastError();
1113  goto done;
1114  }
1115 
1116  /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */
1117 
1118  process->process_handle = info.hProcess;
1119  process->pid = info.dwProcessId;
1120 
1121  /* If the process isn't spawned as detached, assign to the global job object
1122  * so windows will kill it when the parent process dies. */
1123  if (!(options->flags & UV_PROCESS_DETACHED)) {
1125 
1126  if (!AssignProcessToJobObject(uv_global_job_handle_, info.hProcess)) {
1127  /* AssignProcessToJobObject might fail if this process is under job
1128  * control and the job doesn't have the
1129  * JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK flag set, on a Windows version
1130  * that doesn't support nested jobs.
1131  *
1132  * When that happens we just swallow the error and continue without
1133  * establishing a kill-child-on-parent-exit relationship, otherwise
1134  * there would be no way for libuv applications run under job control
1135  * to spawn processes at all.
1136  */
1137  DWORD err = GetLastError();
1138  if (err != ERROR_ACCESS_DENIED)
1139  uv_fatal_error(err, "AssignProcessToJobObject");
1140  }
1141  }
1142 
1143  /* Set IPC pid to all IPC pipes. */
1144  for (i = 0; i < options->stdio_count; i++) {
1145  const uv_stdio_container_t* fdopt = &options->stdio[i];
1146  if (fdopt->flags & UV_CREATE_PIPE &&
1147  fdopt->data.stream->type == UV_NAMED_PIPE &&
1148  ((uv_pipe_t*) fdopt->data.stream)->ipc) {
1149  ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid =
1150  info.dwProcessId;
1151  }
1152  }
1153 
1154  /* Setup notifications for when the child process exits. */
1155  result = RegisterWaitForSingleObject(&process->wait_handle,
1156  process->process_handle, exit_wait_callback, (void*)process, INFINITE,
1157  WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE);
1158  if (!result) {
1159  uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject");
1160  }
1161 
1162  CloseHandle(info.hThread);
1163 
1164  assert(!err);
1165 
1166  /* Make the handle active. It will remain active until the exit callback is
1167  * made or the handle is closed, whichever happens first. */
1169 
1170  /* Cleanup, whether we succeeded or failed. */
1171  done:
1172  uv__free(application);
1173  uv__free(application_path);
1174  uv__free(arguments);
1175  uv__free(cwd);
1176  uv__free(env);
1177  uv__free(alloc_path);
1178 
1179  if (process->child_stdio_buffer != NULL) {
1180  /* Clean up child stdio handles. */
1181  uv__stdio_destroy(process->child_stdio_buffer);
1182  process->child_stdio_buffer = NULL;
1183  }
1184 
1185  return uv_translate_sys_error(err);
1186 }
struct tab * done
Definition: enough.c:233
static const char struct stat static buf struct stat static buf static vhangup int options
Definition: sflib.h:145
unsigned char BYTE
Definition: lz4.c:286
Definition: uv.h:767
uv_stream_t * stream
Definition: uv.h:946
uv_stdio_flags flags
Definition: uv.h:943
union uv_stdio_container_s::@397 data
void uv__stdio_destroy(BYTE *buffer)
WORD uv__stdio_size(BYTE *buffer)
int uv__stdio_create(uv_loop_t *loop, const uv_process_options_t *options, BYTE **buffer_ptr)
HANDLE uv__stdio_handle(BYTE *buffer, int fd)
#define uv__handle_start(h)
Definition: uv-common.h:258
@ UV_INHERIT_FD
Definition: uv.h:924
@ UV_CREATE_PIPE
Definition: uv.h:923
@ UV_PROCESS_WINDOWS_HIDE_CONSOLE
Definition: uv.h:1036
@ UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS
Definition: uv.h:1017
@ UV_PROCESS_WINDOWS_HIDE
Definition: uv.h:1030
@ UV_PROCESS_SETUID
Definition: uv.h:1005
@ UV_PROCESS_SETGID
Definition: uv.h:1011
@ UV_PROCESS_DETACHED
Definition: uv.h:1025
@ UV_PROCESS_WINDOWS_HIDE_GUI
Definition: uv.h:1042
UV_EXTERN void uv_once(uv_once_t *guard, void(*callback)(void))
Definition: thread.c:419
static void uv__init_global_job_handle(void)
Definition: process.c:67
static int uv_utf8_to_utf16_alloc(const char *s, WCHAR **ws_ptr)
Definition: process.c:108
static void uv_process_init(uv_loop_t *loop, uv_process_t *handle)
Definition: process.c:140
static WCHAR * search_path(const WCHAR *file, WCHAR *cwd, const WCHAR *path)
Definition: process.c:340
static uv_once_t uv_global_job_handle_init_guard_
Definition: process.c:64
static WCHAR * find_path(WCHAR *env)
Definition: process.c:831
static void CALLBACK exit_wait_callback(void *data, BOOLEAN didTimeout)
Definition: process.c:849
int make_program_args(char **args, int verbatim_arguments, WCHAR **dst_ptr)
Definition: process.c:526
int make_program_env(char *env_block[], WCHAR **dst_ptr)
Definition: process.c:682

References ARRAY_SIZE, assert(), test-lz4-speed::cwd, uv_stdio_container_s::data, done, DWORD, EINTR, env, EPIPE, err, error(), exit_wait_callback(), find_path(), uv_stdio_container_s::flags, i, info(), int, L, loop, make_program_args(), make_program_env(), NULL, options, path, pid, process(), QUEUE_INIT, QUEUE_INSERT_TAIL, r, read(), search_path(), status, uv_stdio_container_s::stream, uv__chld(), uv__close(), uv__close_nocheckstdio(), UV__ERR, uv__free(), uv__handle_init, uv__handle_start, uv__init_global_job_handle(), uv__make_pipe(), uv__malloc(), uv__process_child_init(), uv__process_close_stream(), uv__process_init_stdio(), uv__process_open_stream(), uv__stdio_create(), uv__stdio_destroy(), uv__stdio_handle(), uv__stdio_size(), UV_CREATE_PIPE, uv_fatal_error(), uv_global_job_handle_, uv_global_job_handle_init_guard_, UV_INHERIT_FD, UV_INHERIT_STREAM, uv_once(), UV_PROCESS_DETACHED, uv_process_init(), UV_PROCESS_SETGID, UV_PROCESS_SETUID, UV_PROCESS_WINDOWS_HIDE, UV_PROCESS_WINDOWS_HIDE_CONSOLE, UV_PROCESS_WINDOWS_HIDE_GUI, UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS, uv_rwlock_wrlock(), uv_rwlock_wrunlock(), uv_signal_start(), uv_translate_sys_error(), and uv_utf8_to_utf16_alloc().

Referenced by invoke_cgi_script(), main(), and setup_workers().

◆ uv_utf8_to_utf16_alloc()

static int uv_utf8_to_utf16_alloc ( const char *  s,
WCHAR **  ws_ptr 
)
static

Definition at line 108 of file process.c.

108  {
109  int ws_len, r;
110  WCHAR* ws;
111 
112  ws_len = MultiByteToWideChar(CP_UTF8,
113  0,
114  s,
115  -1,
116  NULL,
117  0);
118  if (ws_len <= 0) {
119  return GetLastError();
120  }
121 
122  ws = (WCHAR*) uv__malloc(ws_len * sizeof(WCHAR));
123  if (ws == NULL) {
124  return ERROR_OUTOFMEMORY;
125  }
126 
127  r = MultiByteToWideChar(CP_UTF8,
128  0,
129  s,
130  -1,
131  ws,
132  ws_len);
133  assert(r == ws_len);
134 
135  *ws_ptr = ws;
136  return 0;
137 }
static RzSocket * s
Definition: rtr.c:28

References assert(), NULL, r, s, and uv__malloc().

Referenced by uv_spawn().

Variable Documentation

◆ required_vars

const env_var_t required_vars[]
static
Initial value:
= {
E_V("HOMEDRIVE"),
E_V("HOMEPATH"),
E_V("LOGONSERVER"),
E_V("PATH"),
E_V("SYSTEMDRIVE"),
E_V("SYSTEMROOT"),
E_V("TEMP"),
E_V("USERDOMAIN"),
E_V("USERNAME"),
E_V("USERPROFILE"),
E_V("WINDIR"),
}
#define E_V(str)
Definition: process.c:46

Definition at line 48 of file process.c.

Referenced by make_program_env().

◆ uv_global_job_handle_

HANDLE uv_global_job_handle_
static

Definition at line 63 of file process.c.

Referenced by uv__init_global_job_handle(), and uv_spawn().

◆ uv_global_job_handle_init_guard_

uv_once_t uv_global_job_handle_init_guard_ = UV_ONCE_INIT
static

Definition at line 64 of file process.c.

Referenced by uv_spawn().