diff options
Diffstat (limited to 'winsup/cygwin/pinfo.cc')
-rw-r--r-- | winsup/cygwin/pinfo.cc | 801 |
1 files changed, 0 insertions, 801 deletions
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc deleted file mode 100644 index 805f96b..0000000 --- a/winsup/cygwin/pinfo.cc +++ /dev/null @@ -1,801 +0,0 @@ -/* pinfo.cc: process table support - - Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include "winsup.h" -#include <stdlib.h> -#include <time.h> -#include <limits.h> -#include <stdarg.h> -#include "security.h" -#include "path.h" -#include "fhandler.h" -#include "dtable.h" -#include "cygerrno.h" -#include "sigproc.h" -#include "pinfo.h" -#include "cygwin_version.h" -#include "perprocess.h" -#include "environ.h" -#include <assert.h> -#include <ntdef.h> -#include "ntdll.h" -#include "cygthread.h" -#include "shared_info.h" -#include "cygheap.h" -#include "fhandler.h" - -static char NO_COPY pinfo_dummy[sizeof (_pinfo)] = {0}; - -pinfo NO_COPY myself ((_pinfo *)&pinfo_dummy); // Avoid myself != NULL checks - -HANDLE hexec_proc; - -void __stdcall -pinfo_fixup_after_fork () -{ - if (hexec_proc) - CloseHandle (hexec_proc); - /* Keeps the cygpid from being reused. No rights required */ - if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0, - TRUE, 0)) - { - system_printf ("couldn't save current process handle %p, %E", hMainProc); - hexec_proc = NULL; - } -} - -/* Initialize the process table. - This is done once when the dll is first loaded. */ - -void __stdcall -set_myself (pid_t pid, HANDLE h) -{ - DWORD winpid = GetCurrentProcessId (); - if (pid == 1) - pid = cygwin_pid (winpid); - myself.init (pid, PID_IN_USE | PID_MYSELF, h); - myself->dwProcessId = winpid; - myself->process_state |= PID_IN_USE; - myself->start_time = time (NULL); /* Register our starting time. */ - - (void) GetModuleFileName (NULL, myself->progname, sizeof (myself->progname)); - if (!strace.active) - strace.hello (); - InitializeCriticalSection (&myself->lock); - return; -} - -/* Initialize the process table entry for the current task. - This is not called for forked tasks, only execed ones. */ -void __stdcall -pinfo_init (char **envp, int envc) -{ - if (envp) - { - environ_init (envp, envc); - /* spawn has already set up a pid structure for us so we'll use that */ - myself->process_state |= PID_CYGPARENT; - } - else - { - /* Invent our own pid. */ - - set_myself (1); - myself->ppid = 1; - myself->pgid = myself->sid = myself->pid; - myself->ctty = -1; - myself->uid = ILLEGAL_UID; - myself->gid = UNKNOWN_GID; - environ_init (NULL, 0); /* call after myself has been set up */ - } - - debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid); -} - -void -_pinfo::exit (UINT n, bool norecord) -{ - if (this) - { - if (!norecord) - process_state = PID_EXITED; - - /* FIXME: There is a potential race between an execed process and its - parent here. I hated to add a mutex just for this, though. */ - struct rusage r; - fill_rusage (&r, hMainProc); - add_rusage (&rusage_self, &r); - } - - cygthread::terminate (); - sigproc_printf ("Calling ExitProcess %d", n); - ExitProcess (n); -} - -void -pinfo::init (pid_t n, DWORD flag, HANDLE in_h) -{ - if (myself && n == myself->pid) - { - procinfo = myself; - destroy = 0; - h = NULL; - return; - } - - void *mapaddr; - if (!(flag & PID_MYSELF)) - mapaddr = NULL; - else - { - flag &= ~PID_MYSELF; - HANDLE hdummy; - mapaddr = open_shared (NULL, 0, hdummy, 0, SH_MYSELF); - } - - int createit = flag & (PID_IN_USE | PID_EXECED); - DWORD access = FILE_MAP_READ - | (flag & (PID_IN_USE | PID_EXECED | PID_MAP_RW) ? FILE_MAP_WRITE : 0); - for (int i = 0; i < 10; i++) - { - int created; - char mapname[CYG_MAX_PATH]; /* XXX Not a path */ - shared_name (mapname, "cygpid", n); - - int mapsize; - if (flag & PID_EXECED) - mapsize = PINFO_REDIR_SIZE; - else - mapsize = sizeof (_pinfo); - - if (in_h) - { - h = in_h; - created = 0; - } - else if (!createit) - { - h = OpenFileMappingA (access, FALSE, mapname); - created = 0; - } - else - { - char sa_buf[1024]; - PSECURITY_ATTRIBUTES sec_attribs = - sec_user_nih (sa_buf, cygheap->user.sid(), well_known_world_sid, - FILE_MAP_READ); - h = CreateFileMapping (INVALID_HANDLE_VALUE, sec_attribs, - PAGE_READWRITE, 0, mapsize, mapname); - created = h && GetLastError () != ERROR_ALREADY_EXISTS; - } - - if (!h) - { - if (createit) - __seterrno (); - procinfo = NULL; - return; - } - - procinfo = (_pinfo *) MapViewOfFileEx (h, access, 0, 0, 0, mapaddr); - ProtectHandle1 (h, pinfo_shared_handle); - - if ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR) - && cygwin_pid (procinfo->dwProcessId) != procinfo->pid) - { - release (); - set_errno (ENOENT); - return; - } - - if (procinfo->process_state & PID_EXECED) - { - assert (!i); - pid_t realpid = procinfo->pid; - debug_printf ("execed process windows pid %d, cygwin pid %d", n, realpid); - if (realpid == n) - api_fatal ("retrieval of execed process info for pid %d failed due to recursion.", n); - n = realpid; - release (); - if (flag & PID_ALLPIDS) - { - set_errno (ENOENT); - break; - } - continue; - } - - /* In certain rare, pathological cases, it is possible for the shared - memory region to exist for a while after a process has exited. This - should only be a brief occurrence, so rather than introduce some kind - of locking mechanism, just loop. FIXME: I'm sure I'll regret doing it - this way at some point. */ - if (i < 9 && !created && createit && (procinfo->process_state & PID_EXITED)) - { - low_priority_sleep (5); - release (); - continue; - } - - if (!created) - /* nothing */; - else if (!(flag & PID_EXECED)) - procinfo->pid = n; - else - { - procinfo->process_state |= PID_IN_USE | PID_EXECED; - procinfo->pid = myself->pid; - } - break; - } - destroy = 1; -} - -void -pinfo::set_acl() -{ - char sa_buf[1024]; - SECURITY_DESCRIPTOR sd; - - sec_acl ((PACL) sa_buf, true, true, cygheap->user.sid (), - well_known_world_sid, FILE_MAP_READ); - if (!InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION)) - debug_printf ("InitializeSecurityDescriptor %E"); - else if (!SetSecurityDescriptorDacl (&sd, TRUE, (PACL) sa_buf, FALSE)) - debug_printf ("SetSecurityDescriptorDacl %E"); - else if (!SetKernelObjectSecurity (h, DACL_SECURITY_INFORMATION, &sd)) - debug_printf ("SetKernelObjectSecurity %E"); -} - -void -_pinfo::set_ctty (tty_min *tc, int flags, fhandler_tty_slave *arch) -{ - if ((ctty < 0 || ctty == tc->ntty) && !(flags & O_NOCTTY)) - { - ctty = tc->ntty; - syscall_printf ("attached tty%d sid %d, pid %d, tty->pgid %d, tty->sid %d", - tc->ntty, sid, pid, pgid, tc->getsid ()); - - pinfo p (tc->getsid ()); - if (sid == pid && (!p || p->pid == pid || !proc_exists (p))) - { - paranoid_printf ("resetting tty%d sid. Was %d, now %d. pgid was %d, now %d.", - tc->ntty, tc->getsid (), sid, tc->getpgid (), pgid); - /* We are the session leader */ - tc->setsid (sid); - tc->setpgid (pgid); - } - else - sid = tc->getsid (); - if (tc->getpgid () == 0) - tc->setpgid (pgid); - if (cygheap->ctty != arch) - { - debug_printf ("cygheap->ctty %p, arch %p", cygheap->ctty, arch); - if (!cygheap->ctty) - syscall_printf ("ctty NULL"); - else - { - syscall_printf ("ctty %p, usecount %d", cygheap->ctty, - cygheap->ctty->usecount); - if (!--cygheap->ctty->usecount) - cygheap->ctty->close (); - } - cygheap->ctty = arch; - if (arch) - { - arch->usecount++; - debug_printf ("arch usecount for tty%d is %d", tc->ntty, arch->usecount); - } - } - } -} - -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; - extern int __argc_safe; - const char *argv[__argc_safe + 1]; - for (int i = 0; i < __argc_safe; i++) - { - if (IsBadStringPtr (__argv[i], INT32_MAX)) - argv[i] = ""; - else - argv[i] = __argv[i]; - n += strlen (argv[i]) + 1; - } - argv[__argc_safe] = NULL; - 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 (const 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; - } - break; - } - case PICOM_FIFO: - { - int formic; - if (!ReadFile (__fromthem, &formic, sizeof formic, &nr, NULL) - || nr != sizeof formic) - { - /* __seterrno ();*/ // this is run from the signal thread, so don't set errno - goto out; - } - - fhandler_fifo *fh = cygheap->fdtab.find_fifo ((ATOM) formic); - HANDLE it[] = {(fh->get_handle ()), (fh->get_output_handle ())}; - - if (!WriteFile (__tothem, it, sizeof (it), &nr, NULL)) - { - /*__seterrno ();*/ // this is run from the signal thread, so don't set errno - sigproc_printf ("WriteFile read handle failed, %E"); - } - - (void) ReadFile (__fromthem, &nr, sizeof (nr), &nr, NULL); - 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; - va_list args; - - va_start (args, code); - - res.s = NULL; - res.n = 0; - - if (!pid || !this || (dwProcessId != (DWORD) pid && !pinfo (myself->dwProcessId))) - { - 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; - } - - switch (code) - { - case PICOM_FIFO: - { - int formic = va_arg (args, int); - if (!WriteFile (tothem, &formic, sizeof formic, &nr, NULL) || nr != sizeof formic) - { - __seterrno (); - goto err; - } - break; - } - } - - if (sig_send (this, __SIGCOMMUNE)) - goto err; - - /* FIXME: Need something better than an busy loop here */ - bool isalive; - for (int i = 0; (isalive = alive ()) && (i < 10000); i++) - if (myself->hello_pid <= 0) - break; - else - low_priority_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; - switch (code) - { - case PICOM_CMDLINE: - if (!ReadFile (fromthem, &n, sizeof n, &nr, NULL) || nr != sizeof n) - { - __seterrno (); - goto err; - } - 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; - case PICOM_FIFO: - { - DWORD x = ReadFile (fromthem, res.handles, sizeof (res.handles), &nr, NULL); - WriteFile (tothem, &x, sizeof (x), &x, NULL); - if (!x) - goto err; - if (nr != sizeof (res.handles)) - { - set_errno (EPIPE); - goto err; - } - break; - } - } - CloseHandle (tothem); - CloseHandle (fromthem); - goto out; - -err: - if (tome) - CloseHandle (tome); - if (fromthem) - CloseHandle (fromthem); - if (tothem) - CloseHandle (tothem); - if (fromme) - CloseHandle (fromme); - memset (&res, 0, sizeof (res)); - -out: - myself->hello_pid = 0; - LeaveCriticalSection (&myself->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) + 1; - 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 () -{ - if (h) - { -#ifdef DEBUGGING - if (((DWORD) procinfo & 0x77000000) == 0x61000000) - try_to_debug (); -#endif - UnmapViewOfFile (procinfo); - procinfo = NULL; - ForceCloseHandle1 (h, pinfo_shared_handle); - h = NULL; - } -} - -/* DOCTOOL-START - -<sect1 id="func-cygwin-winpid-to-pid"> - <title>cygwin_winpid_to_pid</title> - - <funcsynopsis> - <funcdef>extern "C" pid_t - <function>cygwin_winpid_to_pid</function> - </funcdef> - <paramdef>int <parameter>winpid</parameter></paramdef> - </funcsynopsis> - - <para>Given a windows pid, converts to the corresponding Cygwin -pid, if any. Returns -1 if windows pid does not correspond to -a cygwin pid.</para> - <example> - <title>Example use of cygwin_winpid_to_pid</title> - <programlisting> - extern "C" cygwin_winpid_to_pid (int winpid); - pid_t mypid; - mypid = cygwin_winpid_to_pid (windows_pid); - </programlisting> - </example> -</sect1> - - DOCTOOL-END */ - -extern "C" pid_t -cygwin_winpid_to_pid (int winpid) -{ - pinfo p (cygwin_pid (winpid)); - if (p) - return p->pid; - - set_errno (ESRCH); - return (pid_t) -1; -} - -#include <tlhelp32.h> - -#define slop_pidlist 200 -#define size_pidlist(i) (sizeof (pidlist[0]) * ((i) + 1)) -#define size_pinfolist(i) (sizeof (pinfolist[0]) * ((i) + 1)) - -inline void -winpids::add (DWORD& nelem, bool winpid, DWORD pid) -{ - pid_t cygpid = cygwin_pid (pid); - if (nelem >= npidlist) - { - npidlist += slop_pidlist; - pidlist = (DWORD *) realloc (pidlist, size_pidlist (npidlist + 1)); - pinfolist = (pinfo *) realloc (pinfolist, size_pinfolist (npidlist + 1)); - } - - pinfolist[nelem].init (cygpid, PID_NOREDIR | (winpid ? PID_ALLPIDS : 0) - | pinfo_access); - if (winpid) - goto out; - - if (!pinfolist[nelem]) - { - if (!pinfo_access) - return; - pinfolist[nelem].init (cygpid, PID_NOREDIR | (winpid ? PID_ALLPIDS : 0)); - if (!pinfolist[nelem]) - return; - } - - /* Scan list of previously recorded pids to make sure that this pid hasn't - shown up before. This can happen when a process execs. */ - for (unsigned i = 0; i < nelem; i++) - if (pinfolist[i]->pid == pinfolist[nelem]->pid) - { - if ((_pinfo *) pinfolist[nelem] != (_pinfo *) myself) - pinfolist[nelem].release (); - return; - } - -out: - pidlist[nelem++] = pid; -} - -DWORD -winpids::enumNT (bool winpid) -{ - static DWORD szprocs; - static SYSTEM_PROCESSES *procs; - - DWORD nelem = 0; - if (!szprocs) - procs = (SYSTEM_PROCESSES *) malloc (sizeof (*procs) + (szprocs = 200 * sizeof (*procs))); - - NTSTATUS res; - for (;;) - { - res = NtQuerySystemInformation (SystemProcessesAndThreadsInformation, - procs, szprocs, NULL); - if (res == 0) - break; - - if (res == STATUS_INFO_LENGTH_MISMATCH) - procs = (SYSTEM_PROCESSES *) realloc (procs, szprocs += 200 * sizeof (*procs)); - else - { - system_printf ("error %p reading system process information", res); - return 0; - } - } - - SYSTEM_PROCESSES *px = procs; - for (;;) - { - if (px->ProcessId) - add (nelem, winpid, px->ProcessId); - if (!px->NextEntryDelta) - break; - px = (SYSTEM_PROCESSES *) ((char *) px + px->NextEntryDelta); - } - - return nelem; -} - -DWORD -winpids::enum9x (bool winpid) -{ - DWORD nelem = 0; - - HANDLE h = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); - if (!h) - { - system_printf ("Couldn't create process snapshot, %E"); - return 0; - } - - PROCESSENTRY32 proc; - proc.dwSize = sizeof (proc); - - if (Process32First (h, &proc)) - do - { - if (proc.th32ProcessID) - add (nelem, winpid, proc.th32ProcessID); - } - while (Process32Next (h, &proc)); - - CloseHandle (h); - return nelem; -} - -NO_COPY CRITICAL_SECTION winpids::cs; - -void -winpids::set (bool winpid) -{ - EnterCriticalSection (&cs); - npids = (this->*enum_processes) (winpid); - if (pidlist) - pidlist[npids] = 0; - LeaveCriticalSection (&cs); -} - -void -winpids::init () -{ - InitializeCriticalSection (&cs); -} - -DWORD -winpids::enum_init (bool winpid) -{ - if (wincap.is_winnt ()) - enum_processes = &winpids::enumNT; - else - enum_processes = &winpids::enum9x; - - return (this->*enum_processes) (winpid); -} - -void -winpids::release () -{ - for (unsigned i = 0; i < npids; i++) - if (pinfolist[i] && (_pinfo *) pinfolist[i] != (_pinfo *) myself) - pinfolist[i].release (); -} - -winpids::~winpids () -{ - if (npidlist) - { - release (); - free (pidlist); - free (pinfolist); - } -} |