diff options
author | Christopher Faylor <me@cgf.cx> | 2002-10-30 21:05:18 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2002-10-30 21:05:18 +0000 |
commit | 831d6fa520ed43d055924607a2d9be7fcc3813e9 (patch) | |
tree | f79c2bc5524f448accc0d407fc5b3b5c8ff9e0f4 /winsup/cygwin/pinfo.cc | |
parent | 4c8eba2cf384878e76b5d13acf0d7b22db531463 (diff) | |
download | cygnal-831d6fa520ed43d055924607a2d9be7fcc3813e9.tar.gz cygnal-831d6fa520ed43d055924607a2d9be7fcc3813e9.tar.bz2 cygnal-831d6fa520ed43d055924607a2d9be7fcc3813e9.zip |
* external.cc (cygwin_internal): Implement CW_CMDLINE.
* pinfo.h (SIGCOMMUNE): New signal type.
(commune_result): New structure for commune functions.
(picom): New enum for commune functions.
(_pinfo::hello_pid): New. Pid who's communicating with me.
(_pinfo::tothem): New. Handle of communicating pipe.
(_pinfo::fromthem): Ditto.
(_pinfo::commune_recv): Declare.
(_pinfo::commune_send): Declare.
(_pinfo::alive): Declare.
(_pinfo::cmdline): Declare.
(_pinfo::lock): Declare.
* pinfo.cc (set_myself): Initialize new _pinfo lock.
(_pinfo::alive): Define. Determines if process still exists.
(_pinfo::commune_recv): Define. Receive info from another cooperating process.
(_pinfo::commune_send): Define. Send info to another cooperating process.
(_pinfo::cmdline): Define. Determine command line of a given process.
* include/sys/cygwin.h (CW_CMDLINE): Define.
*sigproc.cc (talktome): Communicate with any processes who want to talk to me.
(wait_sig): Honor __SIGCOMMUNE.
* fhandler.cc (fhandler_virtual::fixup_after_exec): Declare.
* fhandler_proc.cc: Use malloc/free/realloc throughout rather than cmalloc
since buffers don't need to be propagated to subprocesses.
* fhandler_registry.cc: Ditto.
* fhandler_virtual.cc: Ditto.
(fhandler_virtual::fixup_after_exec): Define.
* fhandler_process.cc: Ditto for malloc/free/realloc.
(process_listin): Add "cmdline".
(fhandler_process::fill_filebuf): Implement PROCESS_CMDLINE.
* miscfuncs.cc (isalpha_array): New array populated with xor values for alpha
characters to switch from one case to another.
* string.h (cygwin_strcasematch): New asm implementation of case match.
* string.h (cygwin_nstrcasematch): New asm implementation of counted case
match.
Diffstat (limited to 'winsup/cygwin/pinfo.cc')
-rw-r--r-- | winsup/cygwin/pinfo.cc | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc index 0ffd00edd..b294130d7 100644 --- a/winsup/cygwin/pinfo.cc +++ b/winsup/cygwin/pinfo.cc @@ -66,6 +66,7 @@ set_myself (pid_t pid, HANDLE h) (void) GetModuleFileName (NULL, myself->progname, sizeof (myself->progname)); if (!strace.active) strace.hello (); + InitializeCriticalSection (&myself->lock); return; } @@ -230,6 +231,227 @@ pinfo::init (pid_t n, DWORD flag, HANDLE in_h) destroy = 1; } +bool +_pinfo::alive () +{ + HANDLE h = OpenProcess (PROCESS_QUERY_INFORMATION, false, dwProcessId); + if (h) + CloseHandle (h); + return !!h; +} + +extern char **__argv; + +void +_pinfo::commune_recv () +{ + DWORD nr; + DWORD code; + HANDLE hp; + HANDLE __fromthem = NULL; + HANDLE __tothem = NULL; + + hp = OpenProcess (PROCESS_DUP_HANDLE, false, dwProcessId); + if (!hp) + { + sigproc_printf ("couldn't open handle for pid %d(%u)", pid, dwProcessId); + hello_pid = -1; + return; + } + if (!DuplicateHandle (hp, fromthem, hMainProc, &__fromthem, 0, false, DUPLICATE_SAME_ACCESS)) + { + sigproc_printf ("couldn't duplicate fromthem, %E"); + CloseHandle (hp); + hello_pid = -1; + return; + } + + if (!DuplicateHandle (hp, tothem, hMainProc, &__tothem, 0, false, DUPLICATE_SAME_ACCESS)) + { + sigproc_printf ("couldn't duplicate tothem, %E"); + CloseHandle (__fromthem); + CloseHandle (hp); + hello_pid = -1; + return; + } + + CloseHandle (hp); + hello_pid = 0; + + if (!ReadFile (__fromthem, &code, sizeof code, &nr, NULL) || nr != sizeof code) + { + /* __seterrno ();*/ // this is run from the signal thread, so don't set errno + goto out; + } + + switch (code) + { + case PICOM_CMDLINE: + { + unsigned n = 1; + CloseHandle (__fromthem); __fromthem = NULL; + for (char **a = __argv; *a; a++) + n += strlen (*a) + 1; + if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL)) + { + /*__seterrno ();*/ // this is run from the signal thread, so don't set errno + sigproc_printf ("WriteFile sizeof argv failed, %E"); + } + else + for (char **a = __argv; *a; a++) + if (!WriteFile (__tothem, *a, strlen (*a) + 1, &nr, NULL)) + { + sigproc_printf ("WriteFile arg %d failed, %E", a - __argv); + break; + } + if (!WriteFile (__tothem, "", 1, &nr, NULL)) + { + sigproc_printf ("WriteFile null failed, %E"); + break; + } + } + } + +out: + if (__fromthem) + CloseHandle (__fromthem); + if (__tothem) + CloseHandle (__tothem); +} + +#define PIPEBUFSIZE (16 * sizeof (DWORD)) + +commune_result +_pinfo::commune_send (DWORD code) +{ + HANDLE fromthem = NULL, tome = NULL; + HANDLE fromme = NULL, tothem = NULL; + DWORD nr; + commune_result res; + if (!pid || !this) + { + set_errno (ESRCH); + goto err; + } + if (!CreatePipe (&fromthem, &tome, &sec_all_nih, PIPEBUFSIZE)) + { + sigproc_printf ("first CreatePipe failed, %E"); + __seterrno (); + goto err; + } + if (!CreatePipe (&fromme, &tothem, &sec_all_nih, PIPEBUFSIZE)) + { + sigproc_printf ("first CreatePipe failed, %E"); + __seterrno (); + goto err; + } + EnterCriticalSection (&myself->lock); + myself->tothem = tome; + myself->fromthem = fromme; + myself->hello_pid = pid; + if (!WriteFile (tothem, &code, sizeof code, &nr, NULL) || nr != sizeof code) + { + __seterrno (); + goto err; + } + + if (sig_send (this, __SIGCOMMUNE)) + goto err; + + bool isalive; + while ((isalive = alive ())) + if (myself->hello_pid <= 0) + break; + else + Sleep (0); + + CloseHandle (tome); + tome = NULL; + CloseHandle (fromme); + fromme = NULL; + + if (!isalive) + { + set_errno (ESRCH); + goto err; + } + + if (myself->hello_pid < 0) + { + set_errno (ENOSYS); + goto err; + } + + size_t n; + if (!ReadFile (fromthem, &n, sizeof n, &nr, NULL) || nr != sizeof n) + { + __seterrno (); + goto err; + } + switch (code) + { + case PICOM_CMDLINE: + res.s = (char *) malloc (n); + char *p; + for (p = res.s; ReadFile (fromthem, p, n, &nr, NULL); p += nr) + continue; + if ((unsigned) (p - res.s) != n) + { + __seterrno (); + goto err; + } + res.n = n; + break; + } + CloseHandle (tothem); + CloseHandle (fromthem); + goto out; + +err: + if (tome) + CloseHandle (tome); + if (fromthem) + CloseHandle (fromthem); + if (tothem) + CloseHandle (tothem); + if (fromme) + CloseHandle (fromme); + res.n = 0; +out: + myself->hello_pid = 0; + LeaveCriticalSection (&lock); + return res; +} + +char * +_pinfo::cmdline (size_t& n) +{ + char *s; + if (!this || !pid) + return NULL; + if (pid != myself->pid) + { + commune_result cr = commune_send (PICOM_CMDLINE); + s = cr.s; + n = cr.n; + } + else + { + n = 1; + for (char **a = __argv; *a; a++) + n += strlen (*a); + char *p; + p = s = (char *) malloc (n); + for (char **a = __argv; *a; a++) + { + strcpy (p, *a); + p = strchr (p, '\0') + 1; + } + *p = '\0'; + } + return s; +} + void pinfo::release () { |