newlib/winsup/cygwin/cygheap.h
Christopher Faylor 56a1971526 Throughout use "have_execed" macro rather than "hExeced" global handle.
Throughout rename _PROC_* to _CH_*.
* child_info.h: Include "pinfo.h".
(child_info_types): Rename _PROC_* -> _CH_* to avoid confusion with similarly
named constants.
(_PROC_*): Delete unneeded aliases.
(PROC_*): Ditto.
(CURR_CHILD_INFO_MAGIC): Ditto.
(cchildren): Define using "pinfo_minimal".
(child_info::set_saw_ctrl_c): Move to
(child_info_spawn::set_saw_ctrl_c): Here.
(child_info_spawn::lock): New field.
(child_info_spawn::hExeced): Ditto.
(child_info_spawn::ev): Ditto.
(child_info_spawn::~child_info_spawn): Move to sigproc.cc.
(child_info_spawn::child_info_spawn): Ditto.
(child_info_spawn::cleanup): Declare new function.
(child_info_spawn::set_saw_ctrl_c): Move to this class.  Set flag only when
execed and return true when we have set the flag.
(child_info_spawn::child_info_spawn::signal_myself_exited): New function.
(child_info_spawn::wait_for_myself): Ditto.
(child_info_spawn::has_execed_cygwin): Ditto.
(child_info_spawn::has_execed): Ditto.  Replaces "hExeced" test.
(child_info_spawn::operator HANDLE&): New operator.
(child_info_spawn::worker): Define old "spawn_guts" as class member.
(ch_spawn): Declare.
(have_execed): Define.
(have_execed_cygwin): Ditto.
* cygheap.h: Update comment.
* dcrt0.cc (get_cygwin_startup_info): Use _CH_* enums.
(child_info_spawn::handle_spawn): Ditto.
(dll_crt0_0): Ditto.
(multiple_cygwin_problem): Ditto.
* exceptions.cc (chExeced): Delete obsolete declaration.
(ctrl_c_handler): Reference set_saw_ctrl_c via new ch_spawn global.
* globals.cc (hExeced): Delete.
* pinfo.cc (pinfo::thisproc): Refer to cygheap as ::cygheap for consistency in
handle naming when -DDEBUGGING.
(pinfo::init): Accommodate case where myself.h is known but h0 is passed in.
(pinfo::pinfo): New constructor for setting up a pinfo passed in by previous
exec'or.
(pinfo::proc_waiter): Don't handle subprocess if we're in the process of
exiting due to an exec of a cygwin process.  Don't close rd_proc_pipe here.
Close it when we actually are finished with the process.  Use new
ch_spawn.signal_myself_exited function to let exec stub know that subprocess
has exited.
(pinfo::wait): Clarify debugging output.
(pinfo::release): Use "close_h" to close all handles to avoid races.
(winpids::add): Assume that elements of the array do not need to be zeroed and
are properly initialized or suffer problems on pinfo::release.  Don't close
hProcess since release does that now.
* pinfo.h: Update comment.
(pinfo_minimal): Move some elements from pinfo here so that child_info_spawn
can use them.
(pinfo): Inherit from pinfo_minimal.
(pinfo::pinfo): Modify to accommodate new pinfo_minimal.
(pinfo::allow_remove): New function.
* sigproc.cc (proc_subproc): Use boolean values for true/false.  Implement
PROC_EXEC_CLEANUP.
(proc_terminate): Set ppid = 1 since the procs list will only be iterated when
the process has not execed.  Don't do any cleanup here since it is now handled
in pinfo::release.
(sigproc_init): Initialize sync_proc_subproc earlier.
(child_info::child_info): Assume that all important fields are properly
initialized and avoid memset().
(child_info_spawn::child_info_spawn): Specifically test for execing and then
set up appropriate fields in the struct.
(child_info_spawn::cleanup): Define new function.
(child_info_spawn::record_children): Specifically test for being execed here.
Fill in pinfo_minimal part of children array.
(child_info_spawn::reattach_children): Use constructor to duplicate information
for previous exec'or.  Add more debugging output.
(remove_proc): Force deletion of thread when exiting due to exec.  Rely on
pinfo::cleanup in release.
* sigproc.h (PROC_EXEC_CLEANUP): New enum.
(PROC_DETACHED_CHILD): Delete.
* spawn.cc (chExeced): Delete.
(child_info_spawn::worker): Rename from spawn_guts.  Use elements of
child_info_spawn throughout rather than ch.whatever.  Use ::cygheap to refer to
global rather than element of child_info.  Use wait_for_myself() rather than
waitpid().  Call child_info_spawn::cleanup on function return.
(spawnve): Reflect movement of spawn_guts functionality into
child_info_spawn::worker.
* syscalls.cc (popen): Ditto.
* winsup.h (spawn_guts): Delete declaration.
2011-11-14 01:29:49 +00:00

424 lines
11 KiB
C++

/* cygheap.h: Cygwin heap manager.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011 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 "hires.h"
#include "cygheap_malloc.h"
#define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max)))
struct _cmalloc_entry
{
union
{
DWORD b;
char *ptr;
};
struct _cmalloc_entry *prev;
char data[0];
};
struct cygheap_root_mount_info
{
char posix_path[CYG_MAX_PATH];
unsigned posix_pathlen;
char native_path[CYG_MAX_PATH];
unsigned native_pathlen;
bool caseinsensitive;
};
/* CGF: FIXME This doesn't belong here */
class cygheap_root
{
/* Root directory information.
This is used after a chroot is called. */
struct cygheap_root_mount_info *m;
public:
bool posix_ok (const char *path)
{
if (!m)
return 1;
return path_prefix_p (m->posix_path, path, m->posix_pathlen,
m->caseinsensitive);
}
bool ischroot_native (const char *path)
{
if (!m)
return 1;
return strncasematch (m->native_path, path, m->native_pathlen)
&& (path[m->native_pathlen] == '\\' || !path[m->native_pathlen]);
}
const char *unchroot (const char *path)
{
if (!m)
return path;
const char *p = path + m->posix_pathlen;
if (!*p)
p = "/";
return p;
}
bool exists () {return !!m;}
void set (const char *, const char *, bool);
size_t posix_length () const { return m->posix_pathlen; }
const char *posix_path () const { return m->posix_path; }
size_t native_length () const { return m->native_pathlen; }
const char *native_path () const { return m->native_path; }
};
enum homebodies
{
CH_HOMEDRIVE,
CH_HOMEPATH,
CH_HOME
};
class cygheap_user
{
/* Extendend user information.
The information is derived from the internal_getlogin call
when on a NT system. */
char *pname; /* user's name */
char *plogsrv; /* Logon server, may be FQDN */
char *pdomain; /* Logon domain of the user */
char *homedrive; /* User's home drive */
char *homepath; /* User's home path */
char *psystemroot; /* Value of SYSTEMROOT */
char *pwinname; /* User's name as far as Windows knows it */
char *puserprof; /* User profile */
cygsid effec_cygsid; /* buffer for user's SID */
cygsid saved_cygsid; /* Remains intact even after impersonation */
public:
__uid32_t saved_uid; /* Remains intact even after impersonation */
__gid32_t saved_gid; /* Ditto */
__uid32_t real_uid; /* Remains intact on seteuid, replaced by setuid */
__gid32_t real_gid; /* Ditto */
user_groups groups; /* Primary and supp SIDs */
/* token is needed if set(e)uid should be called. It can be set by a call
to `set_impersonation_token()'. */
HANDLE external_token;
HANDLE internal_token;
HANDLE curr_primary_token;
HANDLE curr_imp_token;
bool ext_token_is_restricted; /* external_token is restricted token */
bool curr_token_is_restricted; /* curr_primary_token is restricted token */
bool setuid_to_restricted; /* switch to restricted token by setuid () */
/* CGF 2002-06-27. I removed the initializaton from this constructor
since this class is always allocated statically. That means that everything
is zero anyway so there is no need to initialize it to zero. Since the
token initialization is always handled during process startup as well,
I've removed the constructor entirely. Please reinstate this if this
situation ever changes.
cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL),
homedrive (NULL), homepath (NULL),
token (INVALID_HANDLE_VALUE) {}
*/
~cygheap_user ();
void init ();
void set_name (const char *new_name);
const char *name () const { return pname; }
const char *env_logsrv (const char *, size_t);
const char *env_homepath (const char *, size_t);
const char *env_homedrive (const char *, size_t);
const char *env_userprofile (const char *, size_t);
const char *env_domain (const char *, size_t);
const char *env_name (const char *, size_t);
const char *env_systemroot (const char *, size_t);
const char *logsrv ()
{
const char *p = env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1);
return (p == almost_null) ? NULL : p;
}
const char *winname ()
{
const char *p = env_name ("USERNAME=", sizeof ("USERNAME=") - 1);
return (p == almost_null) ? NULL : p;
}
const char *domain ()
{
const char *p = env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1);
return (p == almost_null) ? NULL : p;
}
BOOL set_sid (PSID new_sid) {return (BOOL) (effec_cygsid = new_sid);}
BOOL set_saved_sid () { return (BOOL) (saved_cygsid = effec_cygsid); }
PSID sid () { return effec_cygsid; }
PSID saved_sid () { return saved_cygsid; }
const char *ontherange (homebodies what, struct passwd * = NULL);
#define NO_IMPERSONATION NULL
bool issetuid () const { return curr_imp_token != NO_IMPERSONATION; }
HANDLE primary_token () { return curr_primary_token; }
HANDLE imp_token () { return curr_imp_token; }
void deimpersonate ()
{
RevertToSelf ();
}
bool reimpersonate ()
{
if (issetuid ())
return ImpersonateLoggedOnUser (primary_token ());
return true;
}
bool has_impersonation_tokens ()
{ return external_token != NO_IMPERSONATION
|| internal_token != NO_IMPERSONATION
|| curr_primary_token != NO_IMPERSONATION; }
void close_impersonation_tokens ()
{
if (curr_imp_token != NO_IMPERSONATION)
CloseHandle (curr_imp_token);
if (curr_primary_token != NO_IMPERSONATION
&& curr_primary_token != external_token
&& curr_primary_token != internal_token)
CloseHandle (curr_primary_token);
if (external_token != NO_IMPERSONATION)
CloseHandle (external_token);
if (internal_token != NO_IMPERSONATION)
CloseHandle (internal_token);
}
PWCHAR get_windows_id (PWCHAR buf)
{
return effec_cygsid.string (buf);
}
char *get_windows_id (char *buf)
{
return effec_cygsid.string (buf);
}
const char *test_uid (char *&, const char *, size_t)
__attribute__ ((regparm (3)));
};
/* cwd cache stuff. */
class muto;
class cwdstuff
{
private:
char *posix;
HANDLE dir;
DWORD drive_length;
int error; /* This contains an errno number which corresponds
to the problem with this path when trying to start
a native Win32 application. See cwdstuff::set for
how it gets set. See child_info_spawn::worker for how
it's evaluated. */
void override_win32_cwd (bool, ULONG);
public:
UNICODE_STRING win32;
static muto cwd_lock;
const char *get_posix () const { return posix; };
void reset_posix (wchar_t *);
char *get (char *, int = 1, int = 0, unsigned = NT_MAX_PATH);
HANDLE get_handle () { return dir; }
DWORD get_drive (char * dst)
{
cwd_lock.acquire ();
DWORD ret = sys_wcstombs (dst, NT_MAX_PATH, win32.Buffer, drive_length);
cwd_lock.release ();
return ret;
}
int get_error () const { return error; }
const char *get_error_desc () const;
void init ();
int set (path_conv *, const char *);
};
#ifdef DEBUGGING
struct cygheap_debug
{
handle_list starth;
handle_list freeh[500];
};
#endif
struct cygheap_locale
{
mbtowc_p mbtowc;
wctomb_p wctomb;
char charset[ENCODING_LEN + 1];
};
struct user_heap_info
{
void *base;
void *ptr;
void *top;
void *max;
unsigned chunk;
unsigned slop;
};
struct hook_chain
{
void **loc;
const void *func;
struct hook_chain *next;
};
struct mini_cygheap
{
cygheap_locale locale;
};
struct init_cygheap: public mini_cygheap
{
_cmalloc_entry *chain;
char *buckets[32];
cygheap_root root;
cygheap_user user;
user_heap_info user_heap;
mode_t umask;
unsigned long rlim_core;
HANDLE console_h;
cwdstuff cwd;
dtable fdtab;
#ifdef DEBUGGING
cygheap_debug debug;
#endif
struct sigaction *sigs;
fhandler_termios *ctty; /* Current tty */
struct _cygtls **threadlist;
size_t sthreads;
pid_t pid; /* my pid */
HANDLE pid_handle; /* handle for my pid */
struct { /* Equivalent to using LIST_HEAD. */
struct inode_t *lh_first;
} inode_list; /* Global inode pointer for adv. locking. */
hook_chain hooks;
void close_ctty ();
int manage_console_count (const char *, int, bool = false) __attribute__ ((regparm (3)));
private:
int console_count;
};
#define _CYGHEAPSIZE_SLOP (128 * 1024)
#define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + _CYGHEAPSIZE_SLOP)
#define CYGHEAPSIZE_MIN (sizeof (init_cygheap) + (10000 * sizeof (fhandler_union)))
extern init_cygheap *cygheap;
extern void *cygheap_max;
class cygheap_fdmanip
{
protected:
int fd;
bool locked;
public:
cygheap_fdmanip (): fd (-1), locked (false) {}
virtual ~cygheap_fdmanip ()
{
if (locked)
cygheap->fdtab.unlock ();
}
void release ()
{
cygheap->fdtab.release (fd);
}
operator int &() {return fd;}
operator fhandler_base* &() {return cygheap->fdtab[fd];}
operator fhandler_socket* () const {return reinterpret_cast<fhandler_socket *> (cygheap->fdtab[fd]);}
operator fhandler_pipe* () const {return reinterpret_cast<fhandler_pipe *> (cygheap->fdtab[fd]);}
void operator = (fhandler_base *fh) {cygheap->fdtab[fd] = fh;}
fhandler_base *operator -> () const {return cygheap->fdtab[fd];}
bool isopen () const
{
if (cygheap->fdtab[fd])
return true;
set_errno (EBADF);
return false;
}
};
class cygheap_fdnew : public cygheap_fdmanip
{
public:
cygheap_fdnew (int seed_fd = -1, bool lockit = true)
{
if (lockit)
cygheap->fdtab.lock ();
if (seed_fd < 0)
fd = cygheap->fdtab.find_unused_handle ();
else
fd = cygheap->fdtab.find_unused_handle (seed_fd + 1);
if (fd >= 0)
locked = lockit;
else
{
set_errno (EMFILE);
if (lockit)
cygheap->fdtab.unlock ();
locked = false;
}
}
void operator = (fhandler_base *fh) {cygheap->fdtab[fd] = fh;}
};
class cygheap_fdget : public cygheap_fdmanip
{
public:
cygheap_fdget (int fd, bool lockit = false, bool do_set_errno = true)
{
if (lockit)
cygheap->fdtab.lock ();
if (fd >= 0 && fd < (int) cygheap->fdtab.size && cygheap->fdtab[fd] != NULL)
{
this->fd = fd;
locked = lockit;
}
else
{
this->fd = -1;
if (do_set_errno)
set_errno (EBADF);
if (lockit)
cygheap->fdtab.unlock ();
locked = false;
}
}
};
class cygheap_fdenum : public cygheap_fdmanip
{
public:
cygheap_fdenum (bool lockit = false)
{
locked = lockit;
if (lockit)
cygheap->fdtab.lock ();
fd = -1;
}
int next ()
{
while (++fd < (int) cygheap->fdtab.size)
if (cygheap->fdtab[fd] != NULL)
return fd;
return -1;
}
void rewind ()
{
fd = -1;
}
};
void __stdcall cygheap_fixup_in_child (bool);
void __stdcall cygheap_init ();
extern char _cygheap_start[] __attribute__((section(".idata")));