2000-02-17 20:38:33 +01:00
|
|
|
/* pinfo.cc: process table support
|
|
|
|
|
2003-01-10 13:32:49 +01:00
|
|
|
Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003 Red Hat, Inc.
|
2000-02-17 20:38:33 +01:00
|
|
|
|
|
|
|
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. */
|
|
|
|
|
2000-08-02 18:28:18 +02:00
|
|
|
#include "winsup.h"
|
2000-02-17 20:38:33 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <limits.h>
|
2001-07-26 21:22:24 +02:00
|
|
|
#include "security.h"
|
2000-08-22 07:10:20 +02:00
|
|
|
#include "fhandler.h"
|
2001-10-01 06:10:07 +02:00
|
|
|
#include "path.h"
|
2000-08-12 07:35:42 +02:00
|
|
|
#include "dtable.h"
|
2000-08-22 05:58:47 +02:00
|
|
|
#include "cygerrno.h"
|
2000-08-22 07:10:20 +02:00
|
|
|
#include "sigproc.h"
|
|
|
|
#include "pinfo.h"
|
2000-09-08 04:56:55 +02:00
|
|
|
#include "cygwin_version.h"
|
|
|
|
#include "perprocess.h"
|
|
|
|
#include "environ.h"
|
2000-10-15 03:37:07 +02:00
|
|
|
#include <assert.h>
|
2000-11-02 06:25:56 +01:00
|
|
|
#include <ntdef.h>
|
|
|
|
#include "ntdll.h"
|
2002-10-13 20:16:33 +02:00
|
|
|
#include "cygthread.h"
|
2002-10-15 09:03:45 +02:00
|
|
|
#include "shared_info.h"
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2002-06-09 05:54:07 +02:00
|
|
|
static char NO_COPY pinfo_dummy[sizeof (_pinfo)] = {0};
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2000-07-29 18:24:59 +02:00
|
|
|
pinfo NO_COPY myself ((_pinfo *)&pinfo_dummy); // Avoid myself != NULL checks
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2001-09-06 06:41:59 +02:00
|
|
|
HANDLE hexec_proc;
|
2000-10-15 03:37:07 +02:00
|
|
|
|
|
|
|
void __stdcall
|
|
|
|
pinfo_fixup_after_fork ()
|
|
|
|
{
|
|
|
|
if (hexec_proc)
|
|
|
|
CloseHandle (hexec_proc);
|
|
|
|
|
|
|
|
if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hexec_proc, 0,
|
|
|
|
TRUE, DUPLICATE_SAME_ACCESS))
|
|
|
|
{
|
|
|
|
system_printf ("couldn't save current process handle %p, %E", hMainProc);
|
|
|
|
hexec_proc = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-02-17 20:38:33 +01:00
|
|
|
/* Initialize the process table.
|
|
|
|
This is done once when the dll is first loaded. */
|
|
|
|
|
2000-07-29 18:24:59 +02:00
|
|
|
void __stdcall
|
2000-08-24 06:07:50 +02:00
|
|
|
set_myself (pid_t pid, HANDLE h)
|
2000-02-17 20:38:33 +01:00
|
|
|
{
|
2000-07-29 18:24:59 +02:00
|
|
|
DWORD winpid = GetCurrentProcessId ();
|
|
|
|
if (pid == 1)
|
|
|
|
pid = cygwin_pid (winpid);
|
2002-10-14 22:25:52 +02:00
|
|
|
myself.init (pid, PID_IN_USE | PID_MYSELF, h);
|
2000-07-29 18:24:59 +02:00
|
|
|
myself->dwProcessId = winpid;
|
|
|
|
myself->process_state |= PID_IN_USE;
|
2000-02-17 20:38:33 +01:00
|
|
|
myself->start_time = time (NULL); /* Register our starting time. */
|
|
|
|
|
2002-09-22 05:38:57 +02:00
|
|
|
(void) GetModuleFileName (NULL, myself->progname, sizeof (myself->progname));
|
2002-06-19 17:27:27 +02:00
|
|
|
if (!strace.active)
|
|
|
|
strace.hello ();
|
2002-10-30 22:05:18 +01:00
|
|
|
InitializeCriticalSection (&myself->lock);
|
2000-07-29 18:24:59 +02:00
|
|
|
return;
|
2000-02-17 20:38:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize the process table entry for the current task.
|
2002-01-29 03:02:03 +01:00
|
|
|
This is not called for forked tasks, only execed ones. */
|
2000-02-17 20:38:33 +01:00
|
|
|
void __stdcall
|
2000-10-17 01:55:58 +02:00
|
|
|
pinfo_init (char **envp, int envc)
|
2000-02-17 20:38:33 +01:00
|
|
|
{
|
2000-09-03 06:16:35 +02:00
|
|
|
if (envp)
|
2000-02-17 20:38:33 +01:00
|
|
|
{
|
2000-10-17 01:55:58 +02:00
|
|
|
environ_init (envp, envc);
|
2000-02-17 20:38:33 +01:00
|
|
|
/* 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. */
|
|
|
|
|
2000-08-26 03:36:20 +02:00
|
|
|
set_myself (1);
|
2000-07-29 18:24:59 +02:00
|
|
|
myself->ppid = 1;
|
|
|
|
myself->pgid = myself->sid = myself->pid;
|
2000-02-17 20:38:33 +01:00
|
|
|
myself->ctty = -1;
|
* (child_info.h, cygheap.h, dcrt0.cc, dir.cc, fhandler.cc, fhandler.h,
fhandler_clipboard.cc, fhandler_disk_file.cc, fhandler_dsp.cc,
fhandler_floppy.cc, fhandler_mem.cc, fhandler_random.cc,
fhandler_tape.cc, fhandler_zero.cc, grp.cc, mmap.cc, passwd.cc,
pinfo.cc, pinfo.h, pipe.cc, sec_acl.cc, sec_helper.cc, security.cc,
security.h, spawn.cc, syscalls.cc, thread.h, uinfo.cc, winsup.h):
Change usage of uid_t to __uid16_t, gid_t to __gid16_t and
off_t to __off32_t throughout. Use INVALID_UID, INVALID_GID and
INVALID_SEEK instead casting -1 to the appropriate type.
* winsup.h: Define INVALID_UID, INVALID_GID and INVALID_SEEK.
* include/cygwin/acl.h: Define internal __aclent16_t and __aclent32_t
types. Don't declare acl functions when compiling Cygwin.
* include/cygwin/grp.h: Declare getgrgid() and getgrnam() with
correct types for internal usage.
2002-02-10 14:38:51 +01:00
|
|
|
myself->uid = ILLEGAL_UID;
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2000-10-17 01:55:58 +02:00
|
|
|
environ_init (NULL, 0); /* call after myself has been set up */
|
2000-02-17 20:38:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
debug_printf ("pid %d, pgid %d", myself->pid, myself->pgid);
|
|
|
|
}
|
|
|
|
|
2000-10-15 03:37:07 +02:00
|
|
|
void
|
2000-10-17 01:55:58 +02:00
|
|
|
_pinfo::exit (UINT n, bool norecord)
|
2000-10-15 03:37:07 +02:00
|
|
|
{
|
2001-12-26 05:53:34 +01:00
|
|
|
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);
|
|
|
|
}
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2002-10-13 20:16:33 +02:00
|
|
|
cygthread::terminate ();
|
2000-10-17 01:55:58 +02:00
|
|
|
sigproc_printf ("Calling ExitProcess %d", n);
|
|
|
|
ExitProcess (n);
|
2000-02-17 20:38:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-10-21 06:53:49 +02:00
|
|
|
pinfo::init (pid_t n, DWORD flag, HANDLE in_h)
|
2000-02-17 20:38:33 +01:00
|
|
|
{
|
2002-01-29 03:02:03 +01:00
|
|
|
if (myself && n == myself->pid)
|
2000-07-29 18:24:59 +02:00
|
|
|
{
|
2000-08-26 05:48:37 +02:00
|
|
|
procinfo = myself;
|
2000-07-29 18:24:59 +02:00
|
|
|
destroy = 0;
|
|
|
|
h = NULL;
|
|
|
|
return;
|
|
|
|
}
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2002-10-14 22:25:52 +02:00
|
|
|
void *mapaddr;
|
|
|
|
if (!(flag & PID_MYSELF))
|
2002-10-15 09:03:45 +02:00
|
|
|
mapaddr = NULL;
|
2002-10-14 22:25:52 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
flag &= ~PID_MYSELF;
|
2002-10-15 09:03:45 +02:00
|
|
|
HANDLE hdummy;
|
|
|
|
mapaddr = open_shared (NULL, 0, hdummy, 0, SH_MYSELF);
|
2002-10-14 22:25:52 +02:00
|
|
|
}
|
|
|
|
|
2000-10-21 22:57:40 +02:00
|
|
|
int createit = flag & (PID_IN_USE | PID_EXECED);
|
2000-10-15 03:37:07 +02:00
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
|
{
|
|
|
|
int created;
|
|
|
|
char mapname[MAX_PATH];
|
|
|
|
__small_sprintf (mapname, "cygpid.%x", n);
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2000-10-15 03:37:07 +02:00
|
|
|
int mapsize;
|
2000-10-21 06:53:49 +02:00
|
|
|
if (flag & PID_EXECED)
|
2000-10-15 03:37:07 +02:00
|
|
|
mapsize = PINFO_REDIR_SIZE;
|
|
|
|
else
|
|
|
|
mapsize = sizeof (_pinfo);
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2000-10-15 03:37:07 +02:00
|
|
|
if (in_h)
|
|
|
|
{
|
|
|
|
h = in_h;
|
|
|
|
created = 0;
|
|
|
|
}
|
2000-10-21 06:53:49 +02:00
|
|
|
else if (!createit)
|
2000-10-15 03:37:07 +02:00
|
|
|
{
|
|
|
|
h = OpenFileMappingA (FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapname);
|
|
|
|
created = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-01-30 09:10:04 +01:00
|
|
|
h = CreateFileMapping (INVALID_HANDLE_VALUE, &sec_all_nih,
|
|
|
|
PAGE_READWRITE, 0, mapsize, mapname);
|
2000-10-15 03:37:07 +02:00
|
|
|
created = h && GetLastError () != ERROR_ALREADY_EXISTS;
|
|
|
|
}
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2000-10-15 03:37:07 +02:00
|
|
|
if (!h)
|
|
|
|
{
|
2000-10-21 06:53:49 +02:00
|
|
|
if (createit)
|
2000-10-15 03:37:07 +02:00
|
|
|
__seterrno ();
|
|
|
|
procinfo = NULL;
|
|
|
|
return;
|
|
|
|
}
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2002-10-14 22:25:52 +02:00
|
|
|
procinfo = (_pinfo *) MapViewOfFileEx (h, FILE_MAP_READ | FILE_MAP_WRITE,
|
|
|
|
0, 0, 0, mapaddr);
|
2000-10-15 03:37:07 +02:00
|
|
|
ProtectHandle1 (h, pinfo_shared_handle);
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2001-11-01 22:15:53 +01:00
|
|
|
if ((procinfo->process_state & PID_INITIALIZING) && (flag & PID_NOREDIR)
|
|
|
|
&& cygwin_pid (procinfo->dwProcessId) != procinfo->pid)
|
2000-10-20 06:20:21 +02:00
|
|
|
{
|
|
|
|
release ();
|
|
|
|
set_errno (ENOENT);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-10-15 03:37:07 +02:00
|
|
|
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 ();
|
2002-03-15 22:49:12 +01:00
|
|
|
if (flag & PID_ALLPIDS)
|
2002-03-15 00:14:19 +01:00
|
|
|
{
|
|
|
|
set_errno (ENOENT);
|
|
|
|
break;
|
|
|
|
}
|
2000-10-15 03:37:07 +02:00
|
|
|
continue;
|
|
|
|
}
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2000-10-15 03:37:07 +02:00
|
|
|
/* 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. */
|
2000-10-21 06:53:49 +02:00
|
|
|
if (i < 9 && !created && createit && (procinfo->process_state & PID_EXITED))
|
2000-10-15 03:37:07 +02:00
|
|
|
{
|
2002-11-13 20:36:12 +01:00
|
|
|
low_priority_sleep (5);
|
2000-10-15 03:37:07 +02:00
|
|
|
release ();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!created)
|
|
|
|
/* nothing */;
|
2000-10-21 06:53:49 +02:00
|
|
|
else if (!(flag & PID_EXECED))
|
2000-08-26 05:48:37 +02:00
|
|
|
procinfo->pid = n;
|
2000-07-29 18:24:59 +02:00
|
|
|
else
|
|
|
|
{
|
2000-08-26 05:48:37 +02:00
|
|
|
procinfo->process_state |= PID_IN_USE | PID_EXECED;
|
2000-11-03 05:27:03 +01:00
|
|
|
procinfo->pid = myself->pid;
|
2000-07-29 18:24:59 +02:00
|
|
|
}
|
2000-10-15 03:37:07 +02:00
|
|
|
break;
|
2000-02-17 20:38:33 +01:00
|
|
|
}
|
2000-07-29 18:24:59 +02:00
|
|
|
destroy = 1;
|
2000-02-17 20:38:33 +01:00
|
|
|
}
|
2000-10-09 04:53:44 +02:00
|
|
|
|
2002-10-30 22:05:18 +01:00
|
|
|
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;
|
2002-11-05 04:39:25 +01:00
|
|
|
|
|
|
|
res.s = NULL;
|
|
|
|
res.n = 0;
|
|
|
|
|
2003-06-21 02:08:02 +02:00
|
|
|
if (!pid || !this || (dwProcessId != (DWORD) pid && !pinfo (myself->dwProcessId)))
|
2002-10-30 22:05:18 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2002-11-05 05:43:02 +01:00
|
|
|
/* FIXME: Need something better than an busy loop here */
|
2002-10-30 22:05:18 +01:00
|
|
|
bool isalive;
|
2003-07-12 23:37:07 +02:00
|
|
|
for (int i = 0; (isalive = alive ()) && (i < 10000); i++)
|
2002-10-30 22:05:18 +01:00
|
|
|
if (myself->hello_pid <= 0)
|
|
|
|
break;
|
|
|
|
else
|
2002-11-13 20:36:12 +01:00
|
|
|
low_priority_sleep (0);
|
2002-10-30 22:05:18 +01:00
|
|
|
|
|
|
|
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;
|
2003-01-05 07:36:50 +01:00
|
|
|
LeaveCriticalSection (&myself->lock);
|
2002-10-30 22:05:18 +01:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2003-03-08 20:22:08 +01:00
|
|
|
_pinfo::cmdline (size_t& n)
|
2002-10-30 22:05:18 +01:00
|
|
|
{
|
|
|
|
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++)
|
2002-12-16 19:56:33 +01:00
|
|
|
n += strlen (*a) + 1;
|
2002-10-30 22:05:18 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2000-08-26 05:48:37 +02:00
|
|
|
void
|
|
|
|
pinfo::release ()
|
|
|
|
{
|
|
|
|
if (h)
|
|
|
|
{
|
|
|
|
#ifdef DEBUGGING
|
|
|
|
if (((DWORD) procinfo & 0x77000000) == 0x61000000) try_to_debug ();
|
|
|
|
#endif
|
|
|
|
UnmapViewOfFile (procinfo);
|
2000-10-20 06:20:21 +02:00
|
|
|
procinfo = NULL;
|
2000-08-26 05:48:37 +02:00
|
|
|
ForceCloseHandle1 (h, pinfo_shared_handle);
|
|
|
|
h = NULL;
|
|
|
|
}
|
|
|
|
}
|
2000-02-17 20:38:33 +01:00
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
2002-01-29 03:02:03 +01:00
|
|
|
pinfo p (cygwin_pid (winpid));
|
2000-07-29 18:24:59 +02:00
|
|
|
if (p)
|
|
|
|
return p->pid;
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2000-07-29 18:24:59 +02:00
|
|
|
set_errno (ESRCH);
|
|
|
|
return (pid_t) -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <tlhelp32.h>
|
|
|
|
|
2000-11-02 06:25:56 +01:00
|
|
|
#define slop_pidlist 200
|
|
|
|
#define size_pidlist(i) (sizeof (pidlist[0]) * ((i) + 1))
|
2000-11-05 07:42:23 +01:00
|
|
|
#define size_pinfolist(i) (sizeof (pinfolist[0]) * ((i) + 1))
|
2000-11-02 06:25:56 +01:00
|
|
|
|
2000-11-05 07:42:23 +01:00
|
|
|
inline void
|
|
|
|
winpids::add (DWORD& nelem, bool winpid, DWORD pid)
|
|
|
|
{
|
|
|
|
pid_t cygpid = cygwin_pid (pid);
|
|
|
|
if (nelem >= npidlist)
|
|
|
|
{
|
|
|
|
npidlist += slop_pidlist;
|
2001-10-13 19:23:35 +02:00
|
|
|
pidlist = (DWORD *) realloc (pidlist, size_pidlist (npidlist + 1));
|
|
|
|
pinfolist = (pinfo *) realloc (pinfolist, size_pinfolist (npidlist + 1));
|
2000-11-05 07:42:23 +01:00
|
|
|
}
|
|
|
|
|
2002-03-15 22:49:12 +01:00
|
|
|
pinfolist[nelem].init (cygpid, PID_NOREDIR | (winpid ? PID_ALLPIDS : 0));
|
2000-11-05 07:42:23 +01:00
|
|
|
if (winpid)
|
|
|
|
/* nothing to do */;
|
|
|
|
else if (!pinfolist[nelem])
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
/* 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++)
|
2001-01-08 05:02:02 +01:00
|
|
|
if (pinfolist[i]->pid == pinfolist[nelem]->pid)
|
2000-11-05 07:42:23 +01:00
|
|
|
{
|
|
|
|
if ((_pinfo *) pinfolist[nelem] != (_pinfo *) myself)
|
|
|
|
pinfolist[nelem].release ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pidlist[nelem++] = pid;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
|
|
winpids::enumNT (bool winpid)
|
2000-11-02 06:25:56 +01:00
|
|
|
{
|
2001-09-06 06:41:59 +02:00
|
|
|
static DWORD szprocs;
|
2000-11-02 06:25:56 +01:00
|
|
|
static SYSTEM_PROCESSES *procs;
|
|
|
|
|
|
|
|
DWORD nelem = 0;
|
|
|
|
if (!szprocs)
|
2001-10-13 19:23:35 +02:00
|
|
|
procs = (SYSTEM_PROCESSES *) malloc (sizeof (*procs) + (szprocs = 200 * sizeof (*procs)));
|
2000-11-02 06:25:56 +01:00
|
|
|
|
|
|
|
NTSTATUS res;
|
|
|
|
for (;;)
|
|
|
|
{
|
2002-05-30 09:45:30 +02:00
|
|
|
res = NtQuerySystemInformation (SystemProcessesAndThreadsInformation,
|
2000-11-02 06:25:56 +01:00
|
|
|
procs, szprocs, NULL);
|
|
|
|
if (res == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (res == STATUS_INFO_LENGTH_MISMATCH)
|
2001-04-29 04:54:36 +02:00
|
|
|
procs = (SYSTEM_PROCESSES *) realloc (procs, szprocs += 200 * sizeof (*procs));
|
2000-11-02 06:25:56 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
system_printf ("error %p reading system process information", res);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SYSTEM_PROCESSES *px = procs;
|
|
|
|
for (;;)
|
|
|
|
{
|
2000-11-04 06:54:57 +01:00
|
|
|
if (px->ProcessId)
|
2000-11-05 07:42:23 +01:00
|
|
|
add (nelem, winpid, px->ProcessId);
|
|
|
|
if (!px->NextEntryDelta)
|
|
|
|
break;
|
2000-11-02 06:25:56 +01:00
|
|
|
px = (SYSTEM_PROCESSES *) ((char *) px + px->NextEntryDelta);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nelem;
|
|
|
|
}
|
|
|
|
|
2000-11-05 07:42:23 +01:00
|
|
|
DWORD
|
|
|
|
winpids::enum9x (bool winpid)
|
2000-07-29 18:24:59 +02:00
|
|
|
{
|
2000-11-02 06:25:56 +01:00
|
|
|
DWORD nelem = 0;
|
2000-07-29 18:24:59 +02:00
|
|
|
|
2001-06-11 19:57:10 +02:00
|
|
|
HANDLE h = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
|
2000-07-29 18:24:59 +02:00
|
|
|
if (!h)
|
2000-11-02 06:25:56 +01:00
|
|
|
{
|
|
|
|
system_printf ("Couldn't create process snapshot, %E");
|
|
|
|
return 0;
|
|
|
|
}
|
2000-07-29 18:24:59 +02:00
|
|
|
|
|
|
|
PROCESSENTRY32 proc;
|
|
|
|
proc.dwSize = sizeof (proc);
|
2000-11-02 06:25:56 +01:00
|
|
|
|
2001-06-11 19:57:10 +02:00
|
|
|
if (Process32First (h, &proc))
|
2000-07-29 18:24:59 +02:00
|
|
|
do
|
2000-11-02 06:25:56 +01:00
|
|
|
{
|
2000-11-05 07:42:23 +01:00
|
|
|
if (proc.th32ProcessID)
|
|
|
|
add (nelem, winpid, proc.th32ProcessID);
|
2000-11-02 06:25:56 +01:00
|
|
|
}
|
2001-06-11 19:57:10 +02:00
|
|
|
while (Process32Next (h, &proc));
|
2000-11-02 06:25:56 +01:00
|
|
|
|
2000-07-29 18:24:59 +02:00
|
|
|
CloseHandle (h);
|
2000-11-02 06:25:56 +01:00
|
|
|
return nelem;
|
2000-07-29 18:24:59 +02:00
|
|
|
}
|
|
|
|
|
2002-11-29 08:05:26 +01:00
|
|
|
NO_COPY CRITICAL_SECTION winpids::cs;
|
|
|
|
|
2000-07-29 18:24:59 +02:00
|
|
|
void
|
2002-11-29 08:05:26 +01:00
|
|
|
winpids::set (bool winpid)
|
2000-07-29 18:24:59 +02:00
|
|
|
{
|
2002-11-29 08:05:26 +01:00
|
|
|
EnterCriticalSection (&cs);
|
2000-11-05 07:42:23 +01:00
|
|
|
npids = (this->*enum_processes) (winpid);
|
2001-10-13 19:23:35 +02:00
|
|
|
if (pidlist)
|
|
|
|
pidlist[npids] = 0;
|
2002-11-29 08:05:26 +01:00
|
|
|
LeaveCriticalSection (&cs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
winpids::init ()
|
|
|
|
{
|
|
|
|
InitializeCriticalSection (&cs);
|
2000-07-29 18:24:59 +02:00
|
|
|
}
|
|
|
|
|
2000-11-05 07:42:23 +01:00
|
|
|
DWORD
|
|
|
|
winpids::enum_init (bool winpid)
|
2000-07-29 18:24:59 +02:00
|
|
|
{
|
* Makefile.in: Build wincap.o.
* wincap.cc: New file.
* wincap.h: Ditto.
* autoload.cc: Add dynamic load statement for `CreateHardLinkA'.
* dcrt0.cc (os_being_run): Eliminated.
(osname): Ditto.
(iswinnt): Ditto.
(set_os_type): Ditto.
(dll_crt0_1): Call wincap.init() instead of set_os_type().
(_dll_crt0): Ditto.
* environ.cc (set_chunksize): New function.
(parse_thing): `forkchunk' setting now invokes function `set_chunksize'.
* fork.cc (chunksize): Eliminated. Moved to be member of wincap.
* host_dependent.h: Removed.
* syscalls.cc (_link): Try using `CreateHardLinkA' first, if available.
* cygheap.cc, dcrt0.cc, delqueue.cc, dir.cc,
environ.cc, fhandler.cc, fhandler.h, fhandler_console.cc,
fhandler_mem.cc, fork.cc, mmap.cc, net.cc, pinfo.cc, pinfo.h,
security.cc, syscalls.cc, sysconf.cc, syslog.cc, thread.cc,
times.cc, tty.cc, uinfo.cc, uname.cc, winsup.h: Use new wincap
capability check throughout.
* winsup.h: Include wincap.h. Eliminate extern declarations of
`os_being_run' and `iswinnt'. Eliminate `os_type" definition.
* include/cygwin/version.h: Bump version to 1.3.4.
2001-09-12 19:46:37 +02:00
|
|
|
if (wincap.is_winnt ())
|
2000-11-05 07:42:23 +01:00
|
|
|
enum_processes = &winpids::enumNT;
|
2000-07-29 18:24:59 +02:00
|
|
|
else
|
2001-06-11 19:57:10 +02:00
|
|
|
enum_processes = &winpids::enum9x;
|
2000-02-17 20:38:33 +01:00
|
|
|
|
2000-11-05 07:42:23 +01:00
|
|
|
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);
|
|
|
|
}
|
2000-02-17 20:38:33 +01:00
|
|
|
}
|