summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <cgf@redhat.com>2003-09-10 16:23:39 +0000
committerChristopher Faylor <cgf@redhat.com>2003-09-10 16:23:39 +0000
commit19417578ee45b4d89237bd33180d51d2099bd85a (patch)
treee3ad37f0705f674d0a27cc457a44d997a9e59cab
parent847bc8f1111425871f5d072248868c0724ed480f (diff)
downloadgdb-19417578ee45b4d89237bd33180d51d2099bd85a.tar.gz
merge from trunk
-rw-r--r--winsup/cygwin/ChangeLog.branch45
-rw-r--r--winsup/cygwin/Makefile.in10
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/cxx.cc46
-rw-r--r--winsup/cygwin/cygheap.cc4
-rw-r--r--winsup/cygwin/cygheap.h2
-rw-r--r--winsup/cygwin/cygwin.din46
-rw-r--r--winsup/cygwin/dcrt0.cc2
-rw-r--r--winsup/cygwin/dir.cc48
-rw-r--r--winsup/cygwin/exceptions.cc61
-rw-r--r--winsup/cygwin/fhandler.cc6
-rw-r--r--winsup/cygwin/fhandler_console.cc6
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc31
-rw-r--r--winsup/cygwin/fhandler_mem.cc6
-rw-r--r--winsup/cygwin/fhandler_random.cc4
-rw-r--r--winsup/cygwin/fhandler_raw.cc4
-rw-r--r--winsup/cygwin/fhandler_registry.cc24
-rw-r--r--winsup/cygwin/fhandler_tty.cc8
-rw-r--r--winsup/cygwin/fhandler_virtual.cc12
-rw-r--r--winsup/cygwin/fhandler_windows.cc4
-rw-r--r--winsup/cygwin/fork.cc9
-rw-r--r--winsup/cygwin/heap.cc2
-rw-r--r--winsup/cygwin/hires.h57
-rw-r--r--winsup/cygwin/include/cygwin/in.h2
-rw-r--r--winsup/cygwin/include/cygwin/version.h10
-rw-r--r--winsup/cygwin/include/paths.h21
-rw-r--r--winsup/cygwin/include/pty.h18
-rw-r--r--winsup/cygwin/include/sys/cygwin.h3
-rw-r--r--winsup/cygwin/include/sys/dirent.h25
-rw-r--r--winsup/cygwin/include/sys/mman.h8
-rw-r--r--winsup/cygwin/include/sys/utmp.h3
-rw-r--r--winsup/cygwin/lib/iruserok.c319
-rw-r--r--winsup/cygwin/libc/bsdlib.cc165
-rw-r--r--winsup/cygwin/mmap.cc672
-rw-r--r--winsup/cygwin/passwd.cc2
-rw-r--r--winsup/cygwin/path.cc4
-rw-r--r--winsup/cygwin/pinfo.cc17
-rw-r--r--winsup/cygwin/pinfo.h23
-rw-r--r--winsup/cygwin/pipe.cc2
-rw-r--r--winsup/cygwin/shared.cc66
-rw-r--r--winsup/cygwin/shared_info.h4
-rw-r--r--winsup/cygwin/signal.cc21
-rw-r--r--winsup/cygwin/sigproc.cc594
-rw-r--r--winsup/cygwin/sigproc.h22
-rw-r--r--winsup/cygwin/syscalls.cc132
-rw-r--r--winsup/cygwin/sysconf.cc21
-rw-r--r--winsup/cygwin/thread.cc7
-rw-r--r--winsup/cygwin/times.cc52
-rw-r--r--winsup/cygwin/tty.cc7
49 files changed, 1725 insertions, 933 deletions
diff --git a/winsup/cygwin/ChangeLog.branch b/winsup/cygwin/ChangeLog.branch
index 3095997e39d..53554a274ec 100644
--- a/winsup/cygwin/ChangeLog.branch
+++ b/winsup/cygwin/ChangeLog.branch
@@ -1,3 +1,48 @@
+2003-09-09 Christopher Faylor <cgf@redhat.com>
+
+ * exceptions.cc (sig_handle_tty_stop): Check parent PID_NOCLDSTOP
+ rather than erroneously checking *my own* sigtodo.
+ (set_process_mask): Remove pending_signals setting.
+ (sig_handle): Per SUSv3 allow any SIGCONT to clear stopped signals and
+ continue execution. Accept a mask argument.
+ * pinfo.h: Remove signal enums.
+ (_pinfo::getsigmask): Simplify for now.
+ (_pinfo::setsigmask): Ditto.
+ (_pinfo::getsigtodo): Ditto.
+ (_pinfo::setthread2signal): Ditto.
+ (_pinfo::sendsig): New variable.
+ (_pinfo::sigtodo): Eliminate.
+ * signal.cc (kill_worker): Remove reference to thread2signal.
+ * sigproc.cc: Massive signal handling rewrite.
+ (sigelem): New class.
+ (pending_signals): Ditto.
+ (sigqueue): New variable.
+ (sigcatch_nonmain): Delete.
+ (sigcatch_main): Ditto.
+ (sigcatch_nosync): Ditto.
+ (pending_signals): Delete variable.
+ (sig_clear): Send negative signal to signal thread to clear it.
+ (sigpending): Send __SIGPENDING signal to signal thread to have it fill
+ out pending signal mask.
+ (sig_dispatch_pending): Check sigqueue.next flag to determine if
+ anything queued.
+ (sigproc_terminate): Remove semaphore stuff. Just close write side of
+ signal pipe.
+ (sig_send): Rewrite to use new signal pipe stuff.
+ (wait_sig): Ditto.
+ (sig_set_pending): Delete.
+ (getevent): Delete.
+ (pending_signals::add): New function.
+ (pending_signals::del): Ditto.
+ (pending_signals::next): Ditto.
+ * sigproc.h: Move signal enum here.
+ (sig_dispatch_pending): Make this a standard c++ function rather than a
+ "C" function.
+ (sig_handle): Accept an extra argument.
+ * thread.cc (pthread::thread_init_wrapper): Remove nonsensical setting
+ of sigtodo to a local array (!?!).
+ (pthread_kill): Comment out calls to setthread2signal.
+
2003-03-19 Christopher Faylor <cgf@redhat.com>
* dtable.cc (cygwin_attach_handle_to_fd): Eliminate unused variable.
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index d0fc32c7c40..30a75226550 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -74,6 +74,10 @@ fhandler_tty_CFLAGS:=-fomit-frame-pointer
fhandler_virtual_CFLAGS:=-fomit-frame-pointer
fhandler_windows_CFLAGS:=-fomit-frame-pointer
fhandler_zero_CFLAGS:=-fomit-frame-pointer
+regcomp_CFLAGS=-fomit-frame-pointer
+regerror_CFLAGS=-fomit-frame-pointer
+regexec_CFLAGS=-fomit-frame-pointer
+regfree_CFLAGS=-fomit-frame-pointer
CC:=@CC@
# FIXME: Which is it, CC or CC_FOR_TARGET?
@@ -144,9 +148,9 @@ DLL_IMPORTS:=$(w32api_lib)/libkernel32.a
MT_SAFE_OBJECTS:=
# Please maintain this list in sorted order, with maximum files per 80 col line
-DLL_OFILES:=assert.o autoload.o cxx.o cygheap.o cygthread.o dcrt0.o debug.o \
- delqueue.o devices.o dir.o dlfcn.o dll_init.o dtable.o environ.o errno.o \
- exceptions.o exec.o external.o fcntl.o fhandler.o \
+DLL_OFILES:=assert.o autoload.o cxx.o bsdlib.o cygheap.o cygthread.o dcrt0.o \
+ debug.o delqueue.o devices.o dir.o dlfcn.o dll_init.o dtable.o environ.o \
+ errno.o exceptions.o exec.o external.o fcntl.o fhandler.o \
fhandler_clipboard.o fhandler_console.o fhandler_disk_file.o \
fhandler_dsp.o fhandler_fifo.o fhandler_floppy.o fhandler_mem.o \
fhandler_nodevice.o fhandler_proc.o fhandler_process.o \
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index c2c7ae3528b..6344a6d0c14 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -509,6 +509,7 @@ LoadDLLfuncEx2 (IsDebuggerPresent, 0, kernel32, 1, 1)
LoadDLLfunc (IsProcessorFeaturePresent, 4, kernel32);
LoadDLLfuncEx (Process32First, 8, kernel32, 1)
LoadDLLfuncEx (Process32Next, 8, kernel32, 1)
+LoadDLLfuncEx (RegisterServiceProcess, 8, kernel32, 1)
LoadDLLfuncEx (SignalObjectAndWait, 16, kernel32, 1)
LoadDLLfuncEx (SwitchToThread, 0, kernel32, 1)
LoadDLLfunc (TryEnterCriticalSection, 4, kernel32)
diff --git a/winsup/cygwin/cxx.cc b/winsup/cygwin/cxx.cc
new file mode 100644
index 00000000000..9cc1342fe89
--- /dev/null
+++ b/winsup/cygwin/cxx.cc
@@ -0,0 +1,46 @@
+/* cxx.cc
+
+ Copyright 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. */
+
+#if (__GNUC__ >= 3)
+
+#include "winsup.h"
+#include <stdlib.h>
+
+void *
+operator new (size_t s)
+{
+ void *p = calloc (1, s);
+ return p;
+}
+
+void
+operator delete (void *p)
+{
+ free (p);
+}
+
+void *
+operator new[] (size_t s)
+{
+ return ::operator new (s);
+}
+
+void
+operator delete[] (void *p)
+{
+ ::operator delete (p);
+}
+
+extern "C" void
+__cxa_pure_virtual (void)
+{
+ api_fatal ("pure virtual method called");
+}
+#endif
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index f681a5ca2b3..f87cfc41527 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -179,14 +179,14 @@ _csbrk (int sbs)
{
void *prebrk = cygheap_max;
void *prebrka = pagetrunc (prebrk);
- (char *) cygheap_max += sbs;
+ cygheap_max = (char *) cygheap_max + sbs;
if (!sbs || (prebrk != prebrka && prebrka == pagetrunc (cygheap_max)))
/* nothing to do */;
else if (!VirtualAlloc (prebrk, (DWORD) sbs, MEM_COMMIT, PAGE_READWRITE))
{
malloc_printf ("couldn't commit memory for cygwin heap, %E");
__seterrno ();
- (char *) cygheap_max -= sbs;
+ cygheap_max = (char *) cygheap_max - sbs;
return NULL;
}
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 6939507a53c..a06ee9260b0 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -259,7 +259,7 @@ struct init_cygheap
struct sigaction *sigs;
};
-#define CYGHEAPSIZE (sizeof (init_cygheap) + (16000 * sizeof (fhandler_union)) + (5 * 65536))
+#define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + (5 * 65536))
extern init_cygheap *cygheap;
extern void *cygheap_max;
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 85840137abd..227d13569b4 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -141,6 +141,30 @@ alarm
_alarm = alarm
alphasort
_alphasort = alphasort
+argz_add
+__argz_add = argz_add
+argz_add_sep
+__argz_add_sep = argz_add_sep
+argz_append
+__argz_append = argz_append
+argz_count
+__argz_count = argz_count
+argz_create
+__argz_create = argz_create
+argz_create_sep
+__argz_create_sep = argz_create_sep
+argz_delete
+__argz_delete = argz_delete
+argz_extract
+__argz_extract = argz_extract
+argz_insert
+__argz_insert = argz_insert
+argz_next
+__argz_next = argz_next
+argz_replace
+__argz_replace = argz_replace
+argz_stringify
+__argz_stringify = argz_stringify
asctime
_asctime = asctime
asctime_r
@@ -265,6 +289,7 @@ cygwin32_detach_dll = cygwin_detach_dll
cygwin_dll_init
endprotoent = cygwin_endprotoent
endservent = cygwin_endservent
+endusershell
gethostbyaddr = cygwin_gethostbyaddr
gethostbyname = cygwin_gethostbyname
_gethostname = cygwin_gethostname
@@ -278,6 +303,7 @@ getservbyport = cygwin_getservbyport
getservent = cygwin_getservent
getsockname = cygwin_getsockname
getsockopt = cygwin_getsockopt
+getusershell
herror = cygwin_herror
hstrerror = cygwin_hstrerror
inet_addr = cygwin_inet_addr
@@ -311,6 +337,7 @@ cygwin_set_impersonation_token
setprotoent = cygwin_setprotoent
setservent = cygwin_setservent
setsockopt = cygwin_setsockopt
+setusershell
shutdown = cygwin_shutdown
socket = cygwin_socket
cygwin_split_path
@@ -323,6 +350,7 @@ cygwin_win32_to_posix_path_list_buf_size
cygwin32_win32_to_posix_path_list_buf_size = cygwin_win32_to_posix_path_list_buf_size
cygwin_winpid_to_pid
cygwin32_winpid_to_pid = cygwin_winpid_to_pid
+daemon
difftime
_difftime = difftime
dirfd
@@ -362,6 +390,18 @@ endpwent
_endpwent = endpwent
endutent
_endutent = endutent
+envz_add
+__envz_add = envz_add
+envz_entry
+__envz_entry = envz_entry
+envz_get
+__envz_get = envz_get
+envz_merge
+__envz_merge = envz_merge
+envz_remove
+__envz_remove = envz_remove
+envz_strip
+__envz_strip = envz_strip
erand48
_erand48 = erand48
erf
@@ -470,6 +510,7 @@ _fopen = fopen
_fopen64 = fopen64
fork
_fork = fork
+forkpty
fpathconf
fprintf
_fprintf = fprintf
@@ -777,7 +818,10 @@ _logbf = logbf
logf
_logf = logf
login
+login_tty
logout
+logwtmp
+updwtmp
longjmp
_longjmp = longjmp
lrand48
@@ -878,6 +922,7 @@ opendir
_opendir = opendir
openlog
_openlog = openlog
+openpty
pathconf
_pathconf = pathconf
pause
@@ -1022,6 +1067,7 @@ remquo
remquof
rename
_rename = rename
+revoke
rewind
_rewind = rewind
rewinddir
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index afaeff08805..20b2460bb38 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -521,6 +521,7 @@ alloc_stack (child_info_fork *ci)
}
static NO_COPY int mypid = 0;
+int __argc_safe;
int _declspec(dllexport) __argc;
char _declspec(dllexport) **__argv;
vfork_save NO_COPY *main_vfork = NULL;
@@ -722,6 +723,7 @@ dll_crt0_1 ()
}
}
+ __argc_safe = __argc;
if (user_data->premain[0])
for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
user_data->premain[i] (__argc, __argv, user_data);
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
index 88a1689e6fd..902746edf6f 100644
--- a/winsup/cygwin/dir.cc
+++ b/winsup/cygwin/dir.cc
@@ -71,6 +71,14 @@ dirfd (DIR *dir)
return dir->__d_dirent->d_fd;
}
+enum opendir_states
+{
+ opendir_ok = 0,
+ opendir_saw_dot = 1,
+ opendir_saw_dot_dot = 2,
+ opendir_saw_eof = 4
+};
+
/* opendir: POSIX 5.1.2.1 */
extern "C" DIR *
opendir (const char *name)
@@ -89,7 +97,9 @@ opendir (const char *name)
res = NULL;
}
- if (!res && fh)
+ if (res)
+ res->__flags = 0;
+ else if (fh)
delete fh;
return res;
}
@@ -108,7 +118,23 @@ readdir (DIR *dir)
return NULL;
}
- dirent *res = ((fhandler_base *) dir->__d_u.__d_data.__fh)->readdir (dir);
+ dirent *res = ((fhandler_base *) dir->__fh)->readdir (dir);
+
+ if (!res)
+ {
+ if (!(dir->__flags & opendir_saw_dot))
+ {
+ res = dir->__d_dirent;
+ strcpy (res->d_name, ".");
+ dir->__flags |= opendir_saw_dot;
+ }
+ else if (!(dir->__flags & opendir_saw_dot_dot))
+ {
+ res = dir->__d_dirent;
+ strcpy (res->d_name, "..");
+ dir->__flags |= opendir_saw_dot_dot;
+ }
+ }
if (res)
{
@@ -117,11 +143,15 @@ readdir (DIR *dir)
if (res->d_name[0] == '.')
{
if (res->d_name[1] == '\0')
- dir->__d_dirent->d_ino = dir->__d_dirhash;
+ {
+ dir->__d_dirent->d_ino = dir->__d_dirhash;
+ dir->__flags |= opendir_saw_dot;
+ }
else if (res->d_name[1] != '.' || res->d_name[2] != '\0')
goto hashit;
else
{
+ dir->__flags |= opendir_saw_dot_dot;
char *p, up[strlen (dir->__d_dirname) + 1];
strcpy (up, dir->__d_dirname);
if (!(p = strrchr (up, '\\')))
@@ -142,8 +172,8 @@ readdir (DIR *dir)
__ino64_t dino = hash_path_name (dir->__d_dirhash, "\\");
dir->__d_dirent->d_ino = hash_path_name (dino, res->d_name);
}
+ res->__ino32 = dir->__d_dirent->d_ino; // for legacy applications
}
- dir->__d_dirent->old_d_ino = dir->__d_dirent->d_ino; // just truncate
return res;
}
@@ -155,7 +185,7 @@ telldir64 (DIR *dir)
if (dir->__d_cookie != __DIRENT_COOKIE)
return 0;
- return ((fhandler_base *) dir->__d_u.__d_data.__fh)->telldir (dir);
+ return ((fhandler_base *) dir->__fh)->telldir (dir);
}
/* telldir */
@@ -173,7 +203,8 @@ seekdir64 (DIR *dir, _off64_t loc)
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
- return ((fhandler_base *) dir->__d_u.__d_data.__fh)->seekdir (dir, loc);
+ dir->__flags = 0;
+ return ((fhandler_base *) dir->__fh)->seekdir (dir, loc);
}
/* seekdir */
@@ -192,7 +223,8 @@ rewinddir (DIR *dir)
if (dir->__d_cookie != __DIRENT_COOKIE)
return;
- return ((fhandler_base *) dir->__d_u.__d_data.__fh)->rewinddir (dir);
+ dir->__flags = 0;
+ return ((fhandler_base *) dir->__fh)->rewinddir (dir);
}
/* closedir: POSIX 5.1.2.1 */
@@ -212,7 +244,7 @@ closedir (DIR *dir)
/* Reset the marker in case the caller tries to use `dir' again. */
dir->__d_cookie = 0;
- int res = ((fhandler_base *) dir->__d_u.__d_data.__fh)->closedir (dir);
+ int res = ((fhandler_base *) dir->__fh)->closedir (dir);
cygheap->fdtab.release (dir->__d_dirent->d_fd);
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index c63ed20584e..48699b14d54 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -11,12 +11,14 @@ details. */
#include "winsup.h"
#include <imagehlp.h>
#include <stdlib.h>
+#include <setjmp.h>
#include "exceptions.h"
#include "sync.h"
#include "sigproc.h"
#include "pinfo.h"
#include "cygerrno.h"
+#define NEED_VFORK
#include "perthread.h"
#include "shared_info.h"
#include "perprocess.h"
@@ -611,14 +613,13 @@ sig_handle_tty_stop (int sig)
if (my_parent_is_alive ())
{
pinfo parent (myself->ppid);
- if (!(parent->getsig (SIGCHLD).sa_flags & SA_NOCLDSTOP))
+ if (NOTSTATE (parent, PID_NOCLDSTOP))
sig_send (parent, SIGCHLD);
}
sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",
myself->pid, sig, myself->ppid_handle);
if (WaitForSingleObject (sigCONT, INFINITE) != WAIT_OBJECT_0)
api_fatal ("WaitSingleObject failed, %E");
- (void) ResetEvent (sigCONT);
return;
}
}
@@ -963,7 +964,7 @@ set_process_mask (sigset_t newmask)
sigproc_printf ("old mask = %x, new mask = %x", myself->getsigmask (), newmask);
myself->setsigmask (newmask); // Set a new mask
mask_sync->release ();
- if (oldmask != newmask)
+ if (oldmask & ~newmask)
sig_dispatch_pending ();
else
sigproc_printf ("not calling sig_dispatch_pending. sigtid %p current %p",
@@ -972,12 +973,33 @@ set_process_mask (sigset_t newmask)
}
int __stdcall
-sig_handle (int sig)
+sig_handle (int sig, sigset_t mask)
{
- int rc = 1;
+ if (sig == SIGCONT)
+ {
+ DWORD stopped = myself->process_state & PID_STOPPED;
+ myself->stopsig = 0;
+ myself->process_state &= ~PID_STOPPED;
+ /* Clear pending stop signals */
+ sig_clear (SIGSTOP);
+ sig_clear (SIGTSTP);
+ sig_clear (SIGTTIN);
+ sig_clear (SIGTTOU);
+ if (stopped)
+ SetEvent (sigCONT);
+ }
- sigproc_printf ("signal %d", sig);
+ if (sig != SIGKILL && sig != SIGSTOP
+ && (sigismember (&mask, sig) || main_vfork->pid
+ || ISSTATE (myself, PID_STOPPED)))
+ {
+ sigproc_printf ("signal %d blocked", sig);
+ return -1;
+ }
+ int rc = 1;
+
+ sigproc_printf ("signal %d processing", sig);
struct sigaction thissig = myself->getsig (sig);
void *handler = (void *) thissig.sa_handler;
@@ -993,25 +1015,6 @@ sig_handle (int sig)
if (sig == SIGSTOP)
goto stop;
- /* FIXME: Should we still do this if SIGCONT has a handler? */
- if (sig == SIGCONT)
- {
- DWORD stopped = myself->process_state & PID_STOPPED;
- myself->stopsig = 0;
- myself->process_state &= ~PID_STOPPED;
- /* Clear pending stop signals */
- sig_clear (SIGSTOP);
- sig_clear (SIGTSTP);
- sig_clear (SIGTTIN);
- sig_clear (SIGTTOU);
- if (stopped)
- SetEvent (sigCONT);
- /* process pending signals */
-#if 0 // FIXME?
- sig_dispatch_pending ();
-#endif
- }
-
#if 0
char sigmsg[24];
__small_sprintf (sigmsg, "cygwin: signal %d\n", sig);
@@ -1044,23 +1047,23 @@ sig_handle (int sig)
goto dosig;
- stop:
+stop:
/* Eat multiple attempts to STOP */
if (ISSTATE (myself, PID_STOPPED))
goto done;
handler = (void *) sig_handle_tty_stop;
thissig = myself->getsig (SIGSTOP);
- dosig:
+dosig:
/* Dispatch to the appropriate function. */
sigproc_printf ("signal %d, about to call %p", sig, handler);
rc = setup_handler (sig, handler, thissig);
- done:
+done:
sigproc_printf ("returning %d", rc);
return rc;
- exit_sig:
+exit_sig:
if (sig == SIGQUIT || sig == SIGABRT)
{
CONTEXT c;
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 9ecc9edda5c..34f4c531ed7 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -207,7 +207,7 @@ fhandler_base::set_flags (int flags, int supplied_bin)
void
fhandler_base::raw_read (void *ptr, size_t& ulen)
{
-#define bytes_read ((ssize_t) ulen)
+#define bytes_read ulen
HANDLE h = NULL; /* grumble */
int prio = 0; /* ditto */
@@ -253,13 +253,13 @@ fhandler_base::raw_read (void *ptr, size_t& ulen)
if (openflags & O_DIROPEN)
{
set_errno (EISDIR);
- bytes_read = -1;
+ bytes_read = (size_t) -1;
break;
}
default:
syscall_printf ("ReadFile %s failed, %E", get_name ());
__seterrno_from_win_error (errcode);
- bytes_read = -1;
+ bytes_read = (size_t) -1;
break;
}
}
diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index 9409cddd4ee..d85da9e6b5a 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -507,12 +507,12 @@ fhandler_console::read (void *pv, size_t& buflen)
err:
__seterrno ();
- (ssize_t) buflen = -1;
+ buflen = (size_t) -1;
return;
- sig_exit:
+sig_exit:
set_sig_errno (EINTR);
- (ssize_t) buflen = -1;
+ buflen = (size_t) -1;
return;
}
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 5495e889a7b..b034e1f54de 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -612,7 +612,7 @@ fhandler_disk_file::opendir ()
fd = this;
fd->set_nohandle (true);
dir->__d_dirent->d_fd = fd;
- dir->__d_u.__d_data.__fh = this;
+ dir->__fh = this;
/* FindFirstFile doesn't seem to like duplicate /'s. */
len = strlen (dir->__d_dirname);
if (len == 0 || isdirsep (dir->__d_dirname[len - 1]))
@@ -620,7 +620,7 @@ fhandler_disk_file::opendir ()
else
strcat (dir->__d_dirname, "\\*"); /**/
dir->__d_cookie = __DIRENT_COOKIE;
- dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
+ dir->__handle = INVALID_HANDLE_VALUE;
dir->__d_position = 0;
dir->__d_dirhash = get_namehash ();
@@ -641,25 +641,25 @@ fhandler_disk_file::readdir (DIR *dir)
HANDLE handle;
struct dirent *res = NULL;
- if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE
+ if (dir->__handle == INVALID_HANDLE_VALUE
&& dir->__d_position == 0)
{
handle = FindFirstFileA (dir->__d_dirname, &buf);
DWORD lasterr = GetLastError ();
- dir->__d_u.__d_data.__handle = handle;
+ dir->__handle = handle;
if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES))
{
seterrno_from_win_error (__FILE__, __LINE__, lasterr);
return res;
}
}
- else if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE)
+ else if (dir->__handle == INVALID_HANDLE_VALUE)
return res;
- else if (!FindNextFileA (dir->__d_u.__d_data.__handle, &buf))
+ else if (!FindNextFileA (dir->__handle, &buf))
{
DWORD lasterr = GetLastError ();
- (void) FindClose (dir->__d_u.__d_data.__handle);
- dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
+ (void) FindClose (dir->__handle);
+ dir->__handle = INVALID_HANDLE_VALUE;
/* POSIX says you shouldn't set errno when readdir can't
find any more files; so, if another error we leave it set. */
if (lasterr != ERROR_NO_MORE_FILES)
@@ -716,10 +716,10 @@ fhandler_disk_file::seekdir (DIR *dir, _off64_t loc)
void
fhandler_disk_file::rewinddir (DIR *dir)
{
- if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE)
+ if (dir->__handle != INVALID_HANDLE_VALUE)
{
- (void) FindClose (dir->__d_u.__d_data.__handle);
- dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
+ (void) FindClose (dir->__handle);
+ dir->__handle = INVALID_HANDLE_VALUE;
}
dir->__d_position = 0;
}
@@ -728,8 +728,8 @@ int
fhandler_disk_file::closedir (DIR *dir)
{
int res = 0;
- if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE &&
- FindClose (dir->__d_u.__d_data.__handle) == 0)
+ if (dir->__handle != INVALID_HANDLE_VALUE &&
+ FindClose (dir->__handle) == 0)
{
__seterrno ();
res = -1;
@@ -747,12 +747,9 @@ fhandler_cygdrive::fhandler_cygdrive () :
void
fhandler_cygdrive::set_drives ()
{
- const int len = 1 + 26 * DRVSZ;
+ const int len = 2 + 26 * DRVSZ;
char *p = const_cast<char *> (get_win32_name ());
pdrive = p;
- strcpy (p, ".");
- strcpy (p + sizeof ("."), "..");
- p += sizeof (".") + sizeof ("..");
ndrives = GetLogicalDriveStrings (len, p) / DRVSZ;
}
diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc
index 883412f2f7f..70a36371c0a 100644
--- a/winsup/cygwin/fhandler_mem.cc
+++ b/winsup/cygwin/fhandler_mem.cc
@@ -185,7 +185,7 @@ fhandler_dev_mem::read (void *ptr, size_t& ulen)
if (!(get_access () & GENERIC_READ))
{
set_errno (EINVAL);
- (ssize_t) ulen = -1;
+ ulen = (size_t) -1;
return;
}
@@ -210,7 +210,7 @@ fhandler_dev_mem::read (void *ptr, size_t& ulen)
PAGE_READONLY)) != STATUS_SUCCESS)
{
__seterrno_from_win_error (RtlNtStatusToDosError (ret));
- (ssize_t) ulen = -1;
+ ulen = (size_t) -1;
return;
}
@@ -219,7 +219,7 @@ fhandler_dev_mem::read (void *ptr, size_t& ulen)
if (!NT_SUCCESS (ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem)))
{
__seterrno_from_win_error (RtlNtStatusToDosError (ret));
- (ssize_t) ulen = -1;
+ ulen = (size_t) -1;
return;
}
diff --git a/winsup/cygwin/fhandler_random.cc b/winsup/cygwin/fhandler_random.cc
index 55953348f6e..5117ba9f033 100644
--- a/winsup/cygwin/fhandler_random.cc
+++ b/winsup/cygwin/fhandler_random.cc
@@ -119,7 +119,7 @@ fhandler_dev_random::read (void *ptr, size_t& len)
if (!ptr)
{
set_errno (EINVAL);
- (ssize_t) len = -1;
+ len = (size_t) -1;
return;
}
@@ -136,7 +136,7 @@ fhandler_dev_random::read (void *ptr, size_t& len)
}
__seterrno ();
- (ssize_t) len = -1;
+ len = (size_t) -1;
}
_off64_t
diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc
index eae73ed7bfc..38ef837d0e1 100644
--- a/winsup/cygwin/fhandler_raw.cc
+++ b/winsup/cygwin/fhandler_raw.cc
@@ -329,11 +329,11 @@ fhandler_dev_raw::raw_read (void *ptr, size_t& ulen)
}
}
- (ssize_t) ulen = bytes_read;
+ ulen = (size_t) bytes_read;
return;
err:
- (ssize_t) ulen = -1;
+ ulen = (size_t) -1;
return;
}
diff --git a/winsup/cygwin/fhandler_registry.cc b/winsup/cygwin/fhandler_registry.cc
index 42c87e3540b..e9bc37edffd 100644
--- a/winsup/cygwin/fhandler_registry.cc
+++ b/winsup/cygwin/fhandler_registry.cc
@@ -291,13 +291,13 @@ fhandler_registry::readdir (DIR * dir)
res = dir->__d_dirent;
goto out;
}
- if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE
+ if (dir->__handle == INVALID_HANDLE_VALUE
&& dir->__d_position == 0)
{
handle = open_key (path + 1, KEY_READ, false);
- dir->__d_u.__d_data.__handle = handle;
+ dir->__handle = handle;
}
- if (dir->__d_u.__d_data.__handle == INVALID_HANDLE_VALUE)
+ if (dir->__handle == INVALID_HANDLE_VALUE)
goto out;
if (dir->__d_position < SPECIAL_DOT_FILE_COUNT)
{
@@ -311,12 +311,12 @@ retry:
/* For the moment, the type of key is ignored here. when write access is added,
* maybe add an extension for the type of each value?
*/
- error = RegEnumValue ((HKEY) dir->__d_u.__d_data.__handle,
+ error = RegEnumValue ((HKEY) dir->__handle,
(dir->__d_position & ~REG_ENUM_VALUES_MASK) >> 16,
buf, &buf_size, NULL, NULL, NULL, NULL);
else
error =
- RegEnumKeyEx ((HKEY) dir->__d_u.__d_data.__handle, dir->__d_position -
+ RegEnumKeyEx ((HKEY) dir->__handle, dir->__d_position -
SPECIAL_DOT_FILE_COUNT, buf, &buf_size, NULL, NULL, NULL,
NULL);
if (error == ERROR_NO_MORE_ITEMS
@@ -329,8 +329,8 @@ retry:
}
if (error != ERROR_SUCCESS && error != ERROR_MORE_DATA)
{
- RegCloseKey ((HKEY) dir->__d_u.__d_data.__handle);
- dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
+ RegCloseKey ((HKEY) dir->__handle);
+ dir->__handle = INVALID_HANDLE_VALUE;
if (error != ERROR_NO_MORE_ITEMS)
seterrno_from_win_error (__FILE__, __LINE__, error);
goto out;
@@ -372,10 +372,10 @@ fhandler_registry::seekdir (DIR * dir, _off64_t loc)
void
fhandler_registry::rewinddir (DIR * dir)
{
- if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE)
+ if (dir->__handle != INVALID_HANDLE_VALUE)
{
- (void) RegCloseKey ((HKEY) dir->__d_u.__d_data.__handle);
- dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
+ (void) RegCloseKey ((HKEY) dir->__handle);
+ dir->__handle = INVALID_HANDLE_VALUE;
}
dir->__d_position = 0;
return;
@@ -385,8 +385,8 @@ int
fhandler_registry::closedir (DIR * dir)
{
int res = 0;
- if (dir->__d_u.__d_data.__handle != INVALID_HANDLE_VALUE &&
- RegCloseKey ((HKEY) dir->__d_u.__d_data.__handle) != ERROR_SUCCESS)
+ if (dir->__handle != INVALID_HANDLE_VALUE &&
+ RegCloseKey ((HKEY) dir->__handle) != ERROR_SUCCESS)
{
__seterrno ();
res = -1;
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index ecb13416a93..602c6348970 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -737,7 +737,7 @@ fhandler_tty_slave::read (void *ptr, size_t& len)
if (totalread > 0)
break;
set_sig_errno (EINTR);
- (ssize_t) len = -1;
+ len = (size_t) -1;
return;
}
@@ -762,7 +762,7 @@ fhandler_tty_slave::read (void *ptr, size_t& len)
if (!vmin && !time_to_wait)
{
ReleaseMutex (input_mutex);
- (ssize_t) len = bytes_in_pipe;
+ len = (size_t) bytes_in_pipe;
return;
}
@@ -842,7 +842,7 @@ fhandler_tty_slave::read (void *ptr, size_t& len)
waiter = time_to_wait;
}
termios_printf ("%d=read(%x, %d)", totalread, ptr, len);
- (ssize_t) len = totalread;
+ len = (size_t) totalread;
return;
}
@@ -1154,7 +1154,7 @@ fhandler_pty_master::write (const void *ptr, size_t len)
void __stdcall
fhandler_pty_master::read (void *ptr, size_t& len)
{
- (ssize_t) len = process_slave_output ((char *) ptr, len, pktmode);
+ len = (size_t) process_slave_output ((char *) ptr, len, pktmode);
return;
}
diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc
index aedaf018726..258cba287da 100644
--- a/winsup/cygwin/fhandler_virtual.cc
+++ b/winsup/cygwin/fhandler_virtual.cc
@@ -77,9 +77,9 @@ fhandler_virtual::opendir ()
fd = this;
fd->set_nohandle (true);
dir->__d_dirent->d_fd = fd;
- dir->__d_u.__d_data.__fh = this;
+ dir->__fh = this;
dir->__d_cookie = __DIRENT_COOKIE;
- dir->__d_u.__d_data.__handle = INVALID_HANDLE_VALUE;
+ dir->__handle = INVALID_HANDLE_VALUE;
dir->__d_position = 0;
dir->__d_dirhash = get_namehash ();
@@ -179,18 +179,18 @@ fhandler_virtual::read (void *ptr, size_t& len)
if (openflags & O_DIROPEN)
{
set_errno (EISDIR);
- (ssize_t) len = -1;
+ len = (size_t) -1;
return;
}
if (!filebuf)
{
- (ssize_t) len = 0;
+ len = (size_t) 0;
return;
}
if ((ssize_t) len > filesize - position)
- (ssize_t) len = filesize - position;
+ len = (size_t) (filesize - position);
if ((ssize_t) len < 0)
- (ssize_t) len = 0;
+ len = 0;
else
memcpy (ptr, filebuf + position, len);
position += len;
diff --git a/winsup/cygwin/fhandler_windows.cc b/winsup/cygwin/fhandler_windows.cc
index 4affbc6faf4..5964052fa4c 100644
--- a/winsup/cygwin/fhandler_windows.cc
+++ b/winsup/cygwin/fhandler_windows.cc
@@ -87,11 +87,11 @@ fhandler_windows::read (void *buf, size_t& len)
if (len < sizeof (MSG))
{
set_errno (EINVAL);
- (ssize_t) len = -1;
+ len = (size_t) -1;
return;
}
- (ssize_t) len = GetMessage (ptr, hWnd_, 0, 0);
+ len = (size_t) GetMessage (ptr, hWnd_, 0, 0);
if ((ssize_t) len == -1)
__seterrno ();
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 616c7467fef..2fe73667af8 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -633,15 +633,6 @@ fork ()
grouped.hParent = grouped.first_dll = NULL;
grouped.load_dlls = 0;
- if (ISSTATE(myself, PID_SPLIT_HEAP))
- {
- system_printf ("The heap has been split, CYGWIN can't fork this process.");
- system_printf ("Increase the heap_chunk_size in the registry and try again.");
- set_errno (ENOMEM);
- syscall_printf ("-1 = fork (), split heap");
- return -1;
- }
-
void *esp;
__asm__ volatile ("movl %%esp,%0": "=r" (esp));
diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc
index 60cbb4fe134..1bbac313482 100644
--- a/winsup/cygwin/heap.cc
+++ b/winsup/cygwin/heap.cc
@@ -146,7 +146,7 @@ sbrk (int n)
|| VirtualAlloc (cygheap->user_heap.top, newbrksize = commitbytes, MEM_RESERVE, PAGE_NOACCESS))
&& VirtualAlloc (cygheap->user_heap.top, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL)
{
- (char *) cygheap->user_heap.max += pround (newbrksize);
+ cygheap->user_heap.max = (char *) cygheap->user_heap.max + pround (newbrksize);
goto good;
}
diff --git a/winsup/cygwin/hires.h b/winsup/cygwin/hires.h
new file mode 100644
index 00000000000..df4c44c4a1f
--- /dev/null
+++ b/winsup/cygwin/hires.h
@@ -0,0 +1,57 @@
+/* hires.h: Definitions for hires clock calculations
+
+ Copyright 2002 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. */
+
+#ifndef __HIRES_H__
+#define __HIRES_H__
+
+#include <mmsystem.h>
+
+/* Largest delay in ms for sleep and alarm calls.
+ Allow actual delay to exceed requested delay by 10 s.
+ Express as multiple of 1000 (i.e. seconds) + max resolution
+ The tv_sec argument in timeval structures cannot exceed
+ HIRES_DELAY_MAX / 1000 - 1, so that adding fractional part
+ and rounding won't exceed HIRES_DELAY_MAX */
+#define HIRES_DELAY_MAX (((UINT_MAX - 10000) / 1000) * 1000) + 10
+
+class hires_base
+{
+ protected:
+ int inited;
+ public:
+ virtual LONGLONG usecs (bool justdelta) {return 0LL;}
+ virtual ~hires_base () {}
+};
+
+class hires_us : hires_base
+{
+ LARGE_INTEGER primed_ft;
+ LARGE_INTEGER primed_pc;
+ double freq;
+ void prime ();
+ public:
+ LONGLONG usecs (bool justdelta);
+};
+
+class hires_ms : hires_base
+{
+ DWORD initime_ms;
+ LARGE_INTEGER initime_us;
+ static UINT minperiod;
+ UINT prime ();
+ public:
+ LONGLONG usecs (bool justdelta);
+ UINT dmsecs () { return timeGetTime (); }
+ UINT resolution () { return minperiod ?: prime (); }
+
+};
+
+extern hires_ms gtod;
+#endif /*__HIRES_H__*/
diff --git a/winsup/cygwin/include/cygwin/in.h b/winsup/cygwin/include/cygwin/in.h
index a2124552ffd..76bdaaa3e02 100644
--- a/winsup/cygwin/include/cygwin/in.h
+++ b/winsup/cygwin/include/cygwin/in.h
@@ -170,6 +170,7 @@ struct sockaddr_in
#endif
+#ifdef USE_IPV6
/* IPv6 definitions as we start to include them. This is just
a beginning dont get excited 8) */
struct in6_addr
@@ -184,4 +185,5 @@ struct sockaddr_in6
unsigned long sin6_flowinfo;
struct in6_addr sin6_addr;
};
+#endif
#endif /* _CYGWIN_IN_H */
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index b99b0640421..c37f52910d8 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -210,12 +210,20 @@ details. */
88: Export _getreent
89: Export __mempcpy
90: Export _fopen64
+ 91: Export argz_add argz_add_sep argz_append argz_count argz_create
+ argz_create_sep argz_delete argz_extract argz_insert
+ argz_next argz_replace argz_stringify envz_add envz_entry
+ envz_get envz_merge envz_remove envz_strip
+ 92: Export getusershell, setusershell, endusershell
+ 93: Export daemon, forkpty, openpty, iruserok, ruserok, login_tty,
+ openpty, forkpty, revoke, logwtmp, updwtmp
+
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 90
+#define CYGWIN_VERSION_API_MINOR 93
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/paths.h b/winsup/cygwin/include/paths.h
new file mode 100644
index 00000000000..fd03f979034
--- /dev/null
+++ b/winsup/cygwin/include/paths.h
@@ -0,0 +1,21 @@
+/* paths.h
+
+ Copyright 2001 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. */
+
+#ifndef _PATHS_H_
+#define _PATHS_H_
+
+#define _PATH_DEV "/dev/"
+#define _PATH_BSHELL "/bin/sh"
+#define _PATH_LASTLOG "/var/log/lastlog"
+#define _PATH_UTMP "/var/run/utmp"
+#define _PATH_WTMP "/var/log/wtmp"
+#define _PATH_DEVNULL "/dev/null"
+
+#endif /* _PATHS_H_ */
diff --git a/winsup/cygwin/include/pty.h b/winsup/cygwin/include/pty.h
new file mode 100644
index 00000000000..e4b4da03f57
--- /dev/null
+++ b/winsup/cygwin/include/pty.h
@@ -0,0 +1,18 @@
+#ifndef __PTY_H__
+#define __PTY_H__
+
+#include <_ansi.h>
+#include <sys/termios.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _EXFUN(openpty ,(int *, int *, char *, struct termios *, struct winsize *));
+int _EXFUN(forkpty ,(int *, char *, struct termios *, struct winsize *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PTY_H__ */
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index e117175e0c2..9dd46db16ab 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -89,8 +89,7 @@ enum
PID_ORPHANED = 0x0020, /* Member of an orphaned process group. */
PID_ACTIVE = 0x0040, /* Pid accepts signals. */
PID_CYGPARENT = 0x0080, /* Set if parent was a cygwin app. */
- PID_SPLIT_HEAP = 0x0100, /* Set if the heap has been split, */
- /* which means we can't fork again. */
+ PID_UNUSED = 0x0100, /* ... */
PID_MYSELF = 0x0200, /* Flag that pid is me. */
PID_NOCLDSTOP = 0x0400, /* Set if no SIGCHLD signal on stop. */
PID_INITIALIZING = 0x0800, /* Set until ready to receive signals. */
diff --git a/winsup/cygwin/include/sys/dirent.h b/winsup/cygwin/include/sys/dirent.h
index a077169b99b..c3d77c4fbe0 100644
--- a/winsup/cygwin/include/sys/dirent.h
+++ b/winsup/cygwin/include/sys/dirent.h
@@ -1,6 +1,6 @@
/* Posix dirent.h for WIN32.
- Copyright 2001 Red Hat, Inc.
+ Copyright 2001, 2002, 2003 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
@@ -23,7 +23,7 @@ struct dirent
__ino64_t d_ino; /* still junk but with more bits */
long d_fd; /* File descriptor of open directory.
Used since Cygwin 1.3.3. */
- __ino32_t old_d_ino; /* Just for compatibility, it's junk */
+ unsigned __ino32;
char d_name[256]; /* FIXME: use NAME_MAX? */
};
#else
@@ -33,7 +33,7 @@ struct dirent
long d_version;
ino_t d_ino;
long d_fd;
- unsigned long old_d_ino;
+ unsigned long __ino32;
char d_name[256];
};
#else
@@ -51,6 +51,7 @@ struct dirent
#define __DIRENT_COOKIE 0xdede4242
+#pragma pack(push,4)
typedef struct __DIR
{
/* This is first to set alignment in non _COMPILING_NEWLIB case. */
@@ -58,20 +59,12 @@ typedef struct __DIR
struct dirent *__d_dirent;
char *__d_dirname; /* directory name with trailing '*' */
_off_t __d_position; /* used by telldir/seekdir */
- unsigned long __d_dirhash; /* hash of directory name for use by
- readdir */
- union
- {
-#ifdef __INSIDE_CYGWIN__
- struct
- {
- void *__handle;
- void *__fh;
- } __d_data;
-#endif
- char __d_filler[16];
- } __d_u;
+ __ino64_t __d_dirhash; /* hash of directory name for use by readdir */
+ void *__handle;
+ void *__fh;
+ unsigned __flags;
} DIR;
+#pragma pack(pop)
DIR *opendir (const char *);
struct dirent *readdir (DIR *);
diff --git a/winsup/cygwin/include/sys/mman.h b/winsup/cygwin/include/sys/mman.h
index 5059f894af8..13393e9cc27 100644
--- a/winsup/cygwin/include/sys/mman.h
+++ b/winsup/cygwin/include/sys/mman.h
@@ -41,11 +41,11 @@ extern "C" {
#define MS_INVALIDATE 4
#ifndef __INSIDE_CYGWIN__
-extern caddr_t mmap (caddr_t __addr, size_t __len, int __prot, int __flags, int __fd, off_t __off);
+extern void *mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd, off_t __off);
#endif
-extern int munmap (caddr_t __addr, size_t __len);
-extern int mprotect (caddr_t __addr, size_t __len, int __prot);
-extern int msync (caddr_t __addr, size_t __len, int __flags);
+extern int munmap (void *__addr, size_t __len);
+extern int mprotect (void *__addr, size_t __len, int __prot);
+extern int msync (void *__addr, size_t __len, int __flags);
#ifdef __cplusplus
};
diff --git a/winsup/cygwin/include/sys/utmp.h b/winsup/cygwin/include/sys/utmp.h
index 2d959d80683..b78c5631749 100644
--- a/winsup/cygwin/include/sys/utmp.h
+++ b/winsup/cygwin/include/sys/utmp.h
@@ -60,7 +60,8 @@ extern void utmpname (const char *);
void login (struct utmp *);
int logout (char *);
int login_tty (int);
-void logwtmp (char *, char *, char *);
+void updwtmp (const char *, const struct utmp *);
+void logwtmp (const char *, const char *, const char *);
#ifdef __cplusplus
}
diff --git a/winsup/cygwin/lib/iruserok.c b/winsup/cygwin/lib/iruserok.c
new file mode 100644
index 00000000000..5e957184ed9
--- /dev/null
+++ b/winsup/cygwin/lib/iruserok.c
@@ -0,0 +1,319 @@
+/* Based on the rcmd.c.new file distributed with linux libc 5.4.19
+ Adapted to inetutils by Bernhard Rosenkraenzer <bero@startrek.in-trier.de>
+
+ Note that a lot in this file is superfluous; hopefully it won't be a
+ problem for systems that need it for iruserok &c.... */
+/*
+ * Copyright (c) 1983, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef __CYGWIN__
+#define HAVE_MALLOC_H
+#define HAVE_STDLIB_H
+#define HAVE_STRING_H
+#define TIME_WITH_SYS_TIME
+#define PATH_HEQUIV "/etc/hosts.equiv"
+
+static int __ivaliduser();
+static int __icheckhost();
+
+struct hostent *cygwin_gethostbyname (const char *name);
+unsigned long cygwin_inet_addr (const char *cp);
+
+#define gethostbyname cygwin_gethostbyname
+#define inet_addr cygwin_inet_addr
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <pwd.h>
+#include <sys/file.h>
+#include <sys/signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H)
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+#include <netinet/in.h>
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+#include <netdb.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#ifndef __CYGWIN__
+#include <resolv.h>
+#endif
+
+int __check_rhosts_file = 1;
+const char *__rcmd_errstr;
+
+int
+ruserok(rhost, superuser, ruser, luser)
+ const char *rhost;
+ int superuser;
+ const char *ruser;
+ const char *luser;
+{
+ struct hostent *hp;
+ u_long addr;
+ char **ap;
+
+ if ((hp = gethostbyname(rhost)) == NULL)
+ return (-1);
+ for (ap = hp->h_addr_list; *ap; ++ap) {
+ bcopy(*ap, &addr, sizeof(addr));
+ if (iruserok(addr, superuser, ruser, luser) == 0)
+ return (0);
+ }
+ return (-1);
+}
+
+/*
+ * New .rhosts strategy: We are passed an ip address. We spin through
+ * hosts.equiv and .rhosts looking for a match. When the .rhosts only
+ * has ip addresses, we don't have to trust a nameserver. When it
+ * contains hostnames, we spin through the list of addresses the nameserver
+ * gives us and look for a match.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok(raddr, superuser, ruser, luser)
+ u_long raddr;
+ int superuser;
+ const char *ruser;
+ const char *luser;
+{
+ register const char *cp;
+ struct stat sbuf;
+ struct passwd *pwd;
+ FILE *hostf;
+ uid_t uid;
+ int first = 1;
+ char *pbuf;
+
+ first = 1;
+ hostf = superuser ? NULL : fopen(PATH_HEQUIV, "r");
+again:
+ if (hostf) {
+ if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
+ (void) fclose(hostf);
+ return(0);
+ }
+ (void) fclose(hostf);
+ }
+ if (first == 1 && (__check_rhosts_file || superuser)) {
+ first = 0;
+ if ((pwd = getpwnam(luser)) == NULL)
+ return(-1);
+
+ pbuf = malloc (strlen (pwd->pw_dir) + sizeof "/.rhosts");
+ if (! pbuf)
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+ strcpy (pbuf, pwd->pw_dir);
+ strcat (pbuf, "/.rhosts");
+
+ /*
+ * Change effective uid while opening .rhosts. If root and
+ * reading an NFS mounted file system, can't read files that
+ * are protected read/write owner only.
+ */
+ uid = geteuid();
+ (void)seteuid(pwd->pw_uid);
+ hostf = fopen(pbuf, "r");
+ (void)seteuid(uid);
+
+ if (hostf == NULL)
+ return(-1);
+ /*
+ * If not a regular file, or is owned by someone other than
+ * user or root or if writeable by anyone but the owner, quit.
+ */
+ cp = NULL;
+ if (lstat(pbuf, &sbuf) < 0)
+ cp = ".rhosts not regular file";
+ else if (!S_ISREG(sbuf.st_mode))
+ cp = ".rhosts not regular file";
+ else if (fstat(fileno(hostf), &sbuf) < 0)
+ cp = ".rhosts fstat failed";
+ else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
+ cp = "bad .rhosts owner";
+ else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
+ cp = ".rhosts writeable by other than owner";
+ /* If there were any problems, quit. */
+ if (cp) {
+ __rcmd_errstr = (char *) cp;
+ fclose(hostf);
+ return(-1);
+ }
+ goto again;
+ }
+ return (-1);
+}
+
+/*
+ * XXX
+ * Don't make static, used by lpd(8).
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+#ifdef __CYGWIN__
+static
+#endif
+int
+__ivaliduser(hostf, raddr, luser, ruser)
+ FILE *hostf;
+ u_long raddr;
+ const char *luser;
+ const char *ruser;
+{
+ size_t buf_offs = 0;
+ size_t buf_len = 256;
+ char *buf = malloc (buf_len);
+
+ if (! buf)
+ return -1;
+
+ while (fgets(buf + buf_offs, buf_len - buf_offs, hostf)) {
+ /*int ch;*/
+ register char *user, *p;
+
+ if (strchr(buf + buf_offs, '\n') == NULL) {
+ /* No newline yet, read some more. */
+ buf_offs += strlen (buf + buf_offs);
+
+ if (buf_offs >= buf_len - 1) {
+ /* Make more room in BUF. */
+ char *new_buf;
+
+ buf_len += buf_len;
+ new_buf = realloc (buf, buf_len);
+
+ if (! new_buf) {
+ free (buf);
+ return -1;
+ }
+
+ buf = new_buf;
+ }
+
+ continue;
+ }
+
+ buf_offs = 0; /* Start at beginning next time around. */
+
+ p = buf;
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+ /* *p = isupper(*p) ? tolower(*p) : *p; -- Uli */
+ *p = tolower(*p); /* works for linux libc */
+ p++;
+ }
+ if (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ user = p;
+ while (*p != '\n' && *p != ' ' &&
+ *p != '\t' && *p != '\0')
+ p++;
+ } else
+ user = p;
+ *p = '\0';
+
+ if (__icheckhost(raddr, buf) && !strcmp(ruser, *user ? user : luser)) {
+ free (buf);
+ return (0);
+ }
+ }
+
+ free (buf);
+
+ return (-1);
+}
+
+/*
+ * Returns "true" if match, 0 if no match.
+ */
+#ifdef __CYGWIN__
+static
+#endif
+int
+__icheckhost(raddr, lhost)
+ u_long raddr;
+ register char *lhost;
+{
+ register struct hostent *hp;
+ register u_long laddr;
+ register char **pp;
+
+ /* Try for raw ip address first. */
+ if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
+ return (raddr == laddr);
+
+ /* Better be a hostname. */
+ if ((hp = gethostbyname(lhost)) == NULL)
+ return (0);
+
+ /* Spin through ip addresses. */
+ for (pp = hp->h_addr_list; *pp; ++pp)
+ if (!bcmp(&raddr, *pp, sizeof(u_long)))
+ return (1);
+
+ /* No match. */
+ return (0);
+}
diff --git a/winsup/cygwin/libc/bsdlib.cc b/winsup/cygwin/libc/bsdlib.cc
new file mode 100644
index 00000000000..acf43adbfb0
--- /dev/null
+++ b/winsup/cygwin/libc/bsdlib.cc
@@ -0,0 +1,165 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * CV 2003-09-10: Cygwin specific changes applied. Code simplified just
+ * for Cygwin alone.
+ */
+
+#include "winsup.h"
+#include <stdlib.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include "cygerrno.h"
+
+extern "C" int
+daemon (int nochdir, int noclose)
+{
+ int fd;
+
+ switch (fork ())
+ {
+ case -1:
+ return -1;
+ case 0:
+ if (!wincap.is_winnt ())
+ {
+ /* Register as service under 9x/Me which allows to close
+ the parent window with the daemon still running.
+ This function only exists on 9x/Me and is autoloaded
+ so it fails silently on NT. */
+ DWORD WINAPI RegisterServiceProcess (DWORD, DWORD);
+ RegisterServiceProcess (0, 1);
+ }
+ break;
+ default:
+ /* This sleep avoids a race condition which kills the
+ child process if parent is started by a NT/W2K service.
+ FIXME: Is that still true? */
+ Sleep (1000L);
+ _exit (0);
+ }
+ if (setsid () == -1)
+ return -1;
+ if (!nochdir)
+ chdir ("/");
+ if (!noclose && (fd = open (_PATH_DEVNULL, O_RDWR, 0)) >= 0)
+ {
+ dup2 (fd, STDIN_FILENO);
+ dup2 (fd, STDOUT_FILENO);
+ dup2 (fd, STDERR_FILENO);
+ if (fd > 2)
+ close (fd);
+ }
+ return 0;
+}
+
+extern "C" int
+login_tty (int fd)
+{
+ char *fdname;
+ int newfd;
+
+ if (setsid () == -1)
+ return -1;
+ if ((fdname = ttyname (fd)))
+ {
+ if (fd != STDIN_FILENO)
+ close (STDIN_FILENO);
+ if (fd != STDOUT_FILENO)
+ close (STDOUT_FILENO);
+ if (fd != STDERR_FILENO)
+ close (STDERR_FILENO);
+ newfd = open (fdname, O_RDWR);
+ close (newfd);
+ }
+ dup2 (fd, STDIN_FILENO);
+ dup2 (fd, STDOUT_FILENO);
+ dup2 (fd, STDERR_FILENO);
+ if (fd > 2)
+ close (fd);
+ return 0;
+}
+
+extern "C" int
+openpty (int *amaster, int *aslave, char *name, struct termios *termp,
+ struct winsize *winp)
+{
+ int master, slave;
+ char pts[MAX_PATH];
+
+ if ((master = open ("/dev/ptmx", O_RDWR | O_NOCTTY)) >= 0)
+ {
+ grantpt (master);
+ unlockpt (master);
+ strcpy (pts, ptsname (master));
+ revoke (pts);
+ if ((slave = open (pts, O_RDWR | O_NOCTTY)) >= 0)
+ {
+ if (amaster)
+ *amaster = master;
+ if (aslave)
+ *aslave = slave;
+ if (name)
+ strcpy (name, pts);
+ if (termp)
+ tcsetattr (slave, TCSAFLUSH, termp);
+ if (winp)
+ ioctl (slave, TIOCSWINSZ, (char *) winp);
+ return 0;
+ }
+ close (master);
+ }
+ set_errno (ENOENT);
+ return -1;
+}
+
+extern "C" int
+forkpty (int *amaster, char *name, struct termios *termp, struct winsize *winp)
+{
+ int master, slave, pid;
+
+ if (openpty (&master, &slave, name, termp, winp) == -1)
+ return -1;
+ switch (pid = fork ())
+ {
+ case -1:
+ return -1;
+ case 0:
+ close (master);
+ login_tty (slave);
+ return 0;
+ }
+ if (amaster)
+ *amaster = master;
+ close (slave);
+ return pid;
+}
+
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index d2583d2eb44..5ed774273b5 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -27,15 +27,29 @@ details. */
#define PGBITS (sizeof (DWORD)*8)
#define MAPSIZE(pages) howmany ((pages), PGBITS)
-#define MAP_SET(n) (map_map_[(n)/PGBITS] |= (1L << ((n) % PGBITS)))
-#define MAP_CLR(n) (map_map_[(n)/PGBITS] &= ~(1L << ((n) % PGBITS)))
-#define MAP_ISSET(n) (map_map_[(n)/PGBITS] & (1L << ((n) % PGBITS)))
+#define MAP_SET(n) (page_map_[(n)/PGBITS] |= (1L << ((n) % PGBITS)))
+#define MAP_CLR(n) (page_map_[(n)/PGBITS] &= ~(1L << ((n) % PGBITS)))
+#define MAP_ISSET(n) (page_map_[(n)/PGBITS] & (1L << ((n) % PGBITS)))
-/*
- * Simple class used to keep a record of all current
- * mmap areas in a process. Needed so that
- * they can be duplicated after a fork().
- */
+/* Used for accessing the page file (anonymous mmaps). */
+static fhandler_disk_file fh_paging_file;
+
+/* Class structure used to keep a record of all current mmap areas
+ in a process. Needed for bookkeeping all mmaps in a process and
+ for duplicating all mmaps after fork() since mmaps are not propagated
+ to child processes by Windows. All information must be duplicated
+ by hand, see fixup_mmaps_after_fork().
+
+ The class structure:
+
+ One member of class map per process, global variable mmapped_areas.
+ Contains a dynamic class list array. Each list entry represents all
+ mapping to a file, keyed by file descriptor and file name hash.
+ Each list entry contains a dynamic class mmap_record array. Each
+ mmap_record represents exactly one mapping. For each mapping, there's
+ an additional so called `page_map'. It's an array of bits, one bit
+ per mapped memory page. The bit is set if the page is accessible,
+ unset otherwise. */
class mmap_record
{
@@ -46,7 +60,7 @@ class mmap_record
_off64_t offset_;
DWORD size_to_map_;
caddr_t base_address_;
- DWORD *map_map_;
+ DWORD *page_map_;
device dev;
public:
@@ -57,16 +71,13 @@ class mmap_record
offset_ (o),
size_to_map_ (s),
base_address_ (b),
- map_map_ (NULL)
+ page_map_ (NULL)
{
dev.devn = 0;
if (fd >= 0 && !cygheap->fdtab.not_open (fd))
dev = cygheap->fdtab[fd]->dev ();
}
- /* Default Copy constructor/operator=/destructor are ok */
-
- /* Simple accessors */
int get_fd () const { return fdesc_; }
HANDLE get_handle () const { return mapping_handle_; }
device& get_device () { return dev; }
@@ -74,22 +85,61 @@ class mmap_record
DWORD get_offset () const { return offset_; }
DWORD get_size () const { return size_to_map_; }
caddr_t get_address () const { return base_address_; }
- DWORD *get_map () const { return map_map_; }
- void alloc_map (_off64_t off, DWORD len);
- void free_map () { if (map_map_) cfree (map_map_); }
-
- DWORD find_empty (DWORD pages);
- _off64_t map_map (_off64_t off, DWORD len);
- BOOL unmap_map (caddr_t addr, DWORD len);
- void fixup_map (void);
+
+ bool alloc_page_map (_off64_t off, DWORD len);
+ void free_page_map () { if (page_map_) cfree (page_map_); }
+ void fixup_page_map (void);
+
+ DWORD find_unused_pages (DWORD pages);
+ _off64_t map_pages (_off64_t off, DWORD len);
+ BOOL unmap_pages (caddr_t addr, DWORD len);
int access (caddr_t address);
fhandler_base *alloc_fh ();
void free_fh (fhandler_base *fh);
};
+class list
+{
+ private:
+ mmap_record *recs;
+ int nrecs, maxrecs;
+ int fd;
+ DWORD hash;
+
+ public:
+ int get_fd () const { return fd; }
+ DWORD get_hash () const { return hash; }
+ mmap_record *get_record (int i) { return i >= nrecs ? NULL : recs + i; }
+
+ void set (int nfd);
+ mmap_record *add_record (mmap_record r, _off64_t off, DWORD len);
+ bool del_record (int i);
+ void free_recs () { if (recs) cfree (recs); }
+ mmap_record *search_record (_off64_t off, DWORD len);
+ long search_record (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
+ long start);
+};
+
+class map
+{
+ private:
+ list *lists;
+ int nlists, maxlists;
+
+ public:
+ list *get_list (int i) { return i >= nlists ? NULL : lists + i; }
+ list *get_list_by_fd (int fd);
+ list *add_list (int fd);
+ void del_list (int i);
+};
+
+/* This is the global map structure pointer. It's allocated once on the
+ first call to mmap64(). */
+static map *mmapped_areas;
+
DWORD
-mmap_record::find_empty (DWORD pages)
+mmap_record::find_unused_pages (DWORD pages)
{
DWORD mapped_pages = PAGE_CNT (size_to_map_);
DWORD start;
@@ -109,12 +159,15 @@ mmap_record::find_empty (DWORD pages)
return (DWORD)-1;
}
-void
-mmap_record::alloc_map (_off64_t off, DWORD len)
+bool
+mmap_record::alloc_page_map (_off64_t off, DWORD len)
{
/* Allocate one bit per page */
- map_map_ = (DWORD *) ccalloc (HEAP_MMAP, MAPSIZE (PAGE_CNT (size_to_map_)),
- sizeof (DWORD));
+ if (!(page_map_ = (DWORD *) ccalloc (HEAP_MMAP,
+ MAPSIZE (PAGE_CNT (size_to_map_)),
+ sizeof (DWORD))))
+ return false;
+
if (wincap.virtual_protect_works_on_shared_pages ())
{
DWORD old_prot;
@@ -135,15 +188,16 @@ mmap_record::alloc_map (_off64_t off, DWORD len)
while (len-- > 0)
MAP_SET (off + len);
}
+ return true;
}
_off64_t
-mmap_record::map_map (_off64_t off, DWORD len)
+mmap_record::map_pages (_off64_t off, DWORD len)
{
/* Used ONLY if this mapping matches into the chunk of another already
performed mapping in a special case of MAP_ANON|MAP_PRIVATE.
- Otherwise it's job is now done by alloc_map(). */
+ Otherwise it's job is now done by alloc_page_map(). */
DWORD prot, old_prot;
switch (access_mode_)
{
@@ -158,10 +212,10 @@ mmap_record::map_map (_off64_t off, DWORD len)
break;
}
- debug_printf ("map_map (fd=%d, off=%D, len=%u)", fdesc_, off, len);
+ debug_printf ("map_pages (fd=%d, off=%D, len=%u)", fdesc_, off, len);
len = PAGE_CNT (len);
- if ((off = find_empty (len)) == (DWORD)-1)
+ if ((off = find_unused_pages (len)) == (DWORD)-1)
return 0L;
if (wincap.virtual_protect_works_on_shared_pages ()
&& !VirtualProtect (base_address_ + off * getpagesize (),
@@ -177,7 +231,7 @@ mmap_record::map_map (_off64_t off, DWORD len)
}
BOOL
-mmap_record::unmap_map (caddr_t addr, DWORD len)
+mmap_record::unmap_pages (caddr_t addr, DWORD len)
{
DWORD old_prot;
DWORD off = addr - base_address_;
@@ -186,20 +240,20 @@ mmap_record::unmap_map (caddr_t addr, DWORD len)
if (wincap.virtual_protect_works_on_shared_pages ()
&& !VirtualProtect (base_address_ + off * getpagesize (),
len * getpagesize (), PAGE_NOACCESS, &old_prot))
- syscall_printf ("-1 = unmap_map (): %E");
+ syscall_printf ("-1 = unmap_pages (): %E");
for (; len-- > 0; ++off)
MAP_CLR (off);
/* Return TRUE if all pages are free'd which may result in unmapping
the whole chunk. */
for (len = MAPSIZE (PAGE_CNT (size_to_map_)); len > 0; )
- if (map_map_[--len])
+ if (page_map_[--len])
return FALSE;
return TRUE;
}
void
-mmap_record::fixup_map ()
+mmap_record::fixup_page_map ()
{
if (!wincap.virtual_protect_works_on_shared_pages ())
return;
@@ -232,8 +286,6 @@ mmap_record::access (caddr_t address)
return MAP_ISSET (off);
}
-static fhandler_disk_file fh_paging_file;
-
fhandler_base *
mmap_record::alloc_fh ()
{
@@ -259,57 +311,38 @@ mmap_record::free_fh (fhandler_base *fh)
cfree (fh);
}
-class list {
-public:
- mmap_record *recs;
- int nrecs, maxrecs;
- int fd;
- DWORD hash;
- list ();
- ~list ();
- mmap_record *add_record (mmap_record r, _off64_t off, DWORD len);
- void erase (int i);
- void erase ();
- mmap_record *match (_off64_t off, DWORD len);
- long match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
- long start);
-};
-
-list::list ()
-: nrecs (0), maxrecs (10), fd (0), hash (0)
-{
- recs = (mmap_record *) cmalloc (HEAP_MMAP, 10 * sizeof (mmap_record));
-}
-
-list::~list ()
-{
- for (mmap_record *rec = recs; nrecs-- > 0; ++rec)
- rec->free_map ();
- cfree (recs);
-}
-
mmap_record *
list::add_record (mmap_record r, _off64_t off, DWORD len)
{
if (nrecs == maxrecs)
{
+ mmap_record *new_recs;
+ if (maxrecs == 0)
+ new_recs = (mmap_record *)
+ cmalloc (HEAP_MMAP, 5 * sizeof (mmap_record));
+ else
+ new_recs = (mmap_record *)
+ crealloc (recs, (maxrecs + 5) * sizeof (mmap_record));
+ if (!new_recs)
+ return NULL;
maxrecs += 5;
- recs = (mmap_record *) crealloc (recs, maxrecs * sizeof (mmap_record));
+ recs = new_recs;
}
recs[nrecs] = r;
- recs[nrecs].alloc_map (off, len);
+ if (!recs[nrecs].alloc_page_map (off, len))
+ return NULL;
return recs + nrecs++;
}
/* Used in mmap() */
mmap_record *
-list::match (_off64_t off, DWORD len)
+list::search_record (_off64_t off, DWORD len)
{
if (fd == -1 && !off)
{
len = PAGE_CNT (len);
for (int i = 0; i < nrecs; ++i)
- if (recs[i].find_empty (len) != (DWORD)-1)
+ if (recs[i].find_unused_pages (len) != (DWORD)-1)
return recs + i;
}
else
@@ -325,7 +358,7 @@ list::match (_off64_t off, DWORD len)
/* Used in munmap() */
long
-list::match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
+list::search_record (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
_off_t start)
{
caddr_t low, high;
@@ -347,41 +380,27 @@ list::match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
}
void
-list::erase (int i)
-{
- recs[i].free_map ();
- for (; i < nrecs-1; i++)
- recs[i] = recs[i+1];
- nrecs--;
-}
-
-void
-list::erase ()
-{
- erase (nrecs-1);
-}
-
-class map {
-public:
- list **lists;
- int nlists, maxlists;
- map ();
- ~map ();
- list *get_list_by_fd (int fd);
- list *add_list (list *l, int fd);
- void erase (int i);
-};
-
-map::map ()
+list::set (int nfd)
{
- lists = (list **) cmalloc (HEAP_MMAP, 10 * sizeof (list *));
- nlists = 0;
- maxlists = 10;
+ if ((fd = nfd) != -1)
+ hash = cygheap->fdtab[fd]->get_namehash ();
+ nrecs = maxrecs = 0;
+ recs = NULL;
}
-map::~map ()
+bool
+list::del_record (int i)
{
- cfree (lists);
+ if (i < nrecs)
+ {
+ recs[i].free_page_map ();
+ for (; i < nrecs - 1; i++)
+ recs[i] = recs[i + 1];
+ nrecs--;
+ }
+ /* Return true if the list is empty which allows the caller to remove
+ this list from the list array. */
+ return !nrecs;
}
list *
@@ -389,52 +408,49 @@ map::get_list_by_fd (int fd)
{
int i;
for (i=0; i<nlists; i++)
-#if 0 /* The fd isn't sufficient since it could already be another file. */
- if (lists[i]->fd == fd
-#else /* so we use the name hash value to identify the file unless
- it's not an anonymous mapping. */
- if ((fd == -1 && lists[i]->fd == -1)
- || (fd != -1 && lists[i]->hash == cygheap->fdtab[fd]->get_namehash ()))
-#endif
- return lists[i];
+ /* The fd isn't sufficient since it could already be the fd of another
+ file. So we use the name hash value to identify the file unless
+ it's an anonymous mapping in which case the fd (-1) is sufficient. */
+ if ((fd == -1 && lists[i].get_fd () == -1)
+ || (fd != -1
+ && lists[i].get_hash () == cygheap->fdtab[fd]->get_namehash ()))
+ return lists + i;
return 0;
}
list *
-map::add_list (list *l, int fd)
+map::add_list (int fd)
{
- l->fd = fd;
- if (fd != -1)
- l->hash = cygheap->fdtab[fd]->get_namehash ();
if (nlists == maxlists)
{
+ list *new_lists;
+ if (maxlists == 0)
+ new_lists = (list *) cmalloc (HEAP_MMAP, 5 * sizeof (list));
+ else
+ new_lists = (list *) crealloc (lists, (maxlists + 5) * sizeof (list));
+ if (!new_lists)
+ return NULL;
maxlists += 5;
- lists = (list **) crealloc (lists, maxlists * sizeof (list *));
+ lists = new_lists;
}
- lists[nlists++] = l;
- return lists[nlists-1];
+ lists[nlists].set (fd);
+ return lists + nlists++;
}
void
-map::erase (int i)
+map::del_list (int i)
{
- for (; i < nlists-1; i++)
- lists[i] = lists[i+1];
- nlists--;
+ if (i < nlists)
+ {
+ lists[i].free_recs ();
+ for (; i < nlists - 1; i++)
+ lists[i] = lists[i + 1];
+ nlists--;
+ }
}
-/*
- * Code to keep a record of all mmap'ed areas in a process.
- * Needed to duplicate tham in a child of fork().
- * mmap_record classes are kept in an STL list in an STL map, keyed
- * by file descriptor. This is *NOT* duplicated across a fork(), it
- * needs to be specially handled by the fork code.
- */
-
-static map *mmapped_areas;
-
-extern "C" caddr_t
-mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
+extern "C" void *
+mmap64 (void *addr, size_t len, int prot, int flags, int fd, _off64_t off)
{
syscall_printf ("addr %x, len %u, prot %x, flags %x, fd %d, off %D",
addr, len, prot, flags, fd, off);
@@ -464,7 +480,7 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
if (mmapped_areas == NULL)
{
/* First mmap call, create STL map */
- mmapped_areas = new map;
+ mmapped_areas = (map *) ccalloc (HEAP_MMAP, 1, sizeof (map));
if (mmapped_areas == NULL)
{
set_errno (ENOMEM);
@@ -531,9 +547,9 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
if (map_list && fd == -1 && off == 0 && !(flags & MAP_FIXED))
{
mmap_record *rec;
- if ((rec = map_list->match (off, len)) != NULL)
+ if ((rec = map_list->search_record (off, len)) != NULL)
{
- if ((off = rec->map_map (off, len)) == (_off64_t)-1)
+ if ((off = rec->map_pages (off, len)) == (_off64_t)-1)
{
syscall_printf ("-1 = mmap()");
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK, "mmap");
@@ -561,7 +577,7 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
&& (wincap.has_working_copy_on_write () || fd != -1))
access = FILE_MAP_COPY;
- caddr_t base = addr;
+ caddr_t base = (caddr_t)addr;
/* This shifts the base address to the next lower 64K boundary.
The offset is re-added when evaluating the return value. */
if (base)
@@ -575,9 +591,8 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
return MAP_FAILED;
}
- /* Now we should have a successfully mmapped area.
- Need to save it so forked children can reproduce it.
- */
+ /* At this point we should have a successfully mmapped area.
+ Now it's time for bookkeeping stuff. */
if (fd == -1)
gran_len = PAGE_CNT (gran_len) * getpagesize ();
mmap_record mmap_rec (fd, h, access, gran_off, gran_len, base);
@@ -588,7 +603,7 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
if (!map_list)
{
/* Create a new one */
- map_list = new list;
+ map_list = mmapped_areas->add_list (fd);
if (!map_list)
{
fh->munmap (h, base, gran_len);
@@ -597,19 +612,28 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
return MAP_FAILED;
}
- map_list = mmapped_areas->add_list (map_list, fd);
}
/* Insert into the list */
- mmap_record *rec = map_list->add_record (mmap_rec, off, len > gran_len ? gran_len : len);
+ mmap_record *rec = map_list->add_record (mmap_rec, off,
+ len > gran_len ? gran_len : len);
+ if (!rec)
+ {
+ fh->munmap (h, base, gran_len);
+ set_errno (ENOMEM);
+ syscall_printf ("-1 = mmap(): ENOMEM");
+ ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
+ return MAP_FAILED;
+ }
+
caddr_t ret = rec->get_address () + (off - gran_off);
syscall_printf ("%x = mmap() succeeded", ret);
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
return ret;
}
-extern "C" caddr_t
-mmap (caddr_t addr, size_t len, int prot, int flags, int fd, _off_t off)
+extern "C" void *
+mmap (void *addr, size_t len, int prot, int flags, int fd, _off_t off)
{
return mmap64 (addr, len, prot, flags, fd, (_off64_t)off);
}
@@ -617,7 +641,7 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, _off_t off)
/* munmap () removes all mmapped pages between addr and addr+len. */
extern "C" int
-munmap (caddr_t addr, size_t len)
+munmap (void *addr, size_t len)
{
syscall_printf ("munmap (addr %x, len %u)", addr, len);
@@ -640,27 +664,33 @@ munmap (caddr_t addr, size_t len)
/* Iterate through the map, unmap pages between addr and addr+len
in all maps. */
-
- for (int it = 0; it < mmapped_areas->nlists; ++it)
+ list *map_list;
+ for (int list_idx = 0;
+ (map_list = mmapped_areas->get_list (list_idx));
+ ++list_idx)
{
- list *map_list = mmapped_areas->lists[it];
- if (map_list)
- {
- long li = -1;
- caddr_t u_addr;
- DWORD u_len;
+ long record_idx = -1;
+ caddr_t u_addr;
+ DWORD u_len;
- while ((li = map_list->match(addr, len, u_addr, u_len, li)) >= 0)
+ while ((record_idx = map_list->search_record((caddr_t)addr, len, u_addr,
+ u_len, record_idx)) >= 0)
+ {
+ mmap_record *rec = map_list->get_record (record_idx);
+ if (rec->unmap_pages (u_addr, u_len))
{
- mmap_record *rec = map_list->recs + li;
- if (rec->unmap_map (u_addr, u_len))
- {
- fhandler_base *fh = rec->alloc_fh ();
- fh->munmap (rec->get_handle (), addr, len);
- rec->free_fh (fh);
+ /* The whole record has been unmapped, so... */
+ fhandler_base *fh = rec->alloc_fh ();
+ fh->munmap (rec->get_handle (), (caddr_t)addr, len);
+ rec->free_fh (fh);
- /* Delete the entry. */
- map_list->erase (li);
+ /* ...delete the record. */
+ if (map_list->del_record (record_idx--))
+ {
+ /* Yay, the last record has been removed from the list,
+ we can remove the list now, too. */
+ mmapped_areas->del_list (list_idx--);
+ break;
}
}
}
@@ -674,7 +704,7 @@ munmap (caddr_t addr, size_t len)
/* Sync file with memory. Ignore flags for now. */
extern "C" int
-msync (caddr_t addr, size_t len, int flags)
+msync (void *addr, size_t len, int flags)
{
syscall_printf ("addr = %x, len = %u, flags = %x",
addr, len, flags);
@@ -701,33 +731,35 @@ msync (caddr_t addr, size_t len, int flags)
/* Iterate through the map, looking for the mmapped area.
Error if not found. */
- for (int it = 0; it < mmapped_areas->nlists; ++it)
+ list *map_list;
+ for (int list_idx = 0;
+ (map_list = mmapped_areas->get_list (list_idx));
+ ++list_idx)
{
- list *map_list = mmapped_areas->lists[it];
- if (map_list != 0)
+ mmap_record *rec;
+ for (int record_idx = 0;
+ (rec = map_list->get_record (record_idx));
+ ++record_idx)
{
- for (int li = 0; li < map_list->nrecs; ++li)
+ if (rec->access ((caddr_t)addr))
{
- mmap_record *rec = map_list->recs + li;
- if (rec->access (addr))
- {
- /* Check whole area given by len. */
- for (DWORD i = getpagesize (); i < len; ++i)
- if (!rec->access (addr + i))
- goto invalid_address_range;
- fhandler_base *fh = rec->alloc_fh ();
- int ret = fh->msync (rec->get_handle (), addr, len, flags);
- rec->free_fh (fh);
-
- if (ret)
- syscall_printf ("%d = msync(): %E", ret);
- else
- syscall_printf ("0 = msync()");
-
- ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK,
- "msync");
- return 0;
- }
+ /* Check whole area given by len. */
+ for (DWORD i = getpagesize (); i < len; ++i)
+ if (!rec->access ((caddr_t)addr + i))
+ goto invalid_address_range;
+ fhandler_base *fh = rec->alloc_fh ();
+ int ret = fh->msync (rec->get_handle (), (caddr_t)addr, len,
+ flags);
+ rec->free_fh (fh);
+
+ if (ret)
+ syscall_printf ("%d = msync(): %E", ret);
+ else
+ syscall_printf ("0 = msync()");
+
+ ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK,
+ "msync");
+ return 0;
}
}
}
@@ -741,6 +773,62 @@ invalid_address_range:
return -1;
}
+/* Set memory protection */
+
+extern "C" int
+mprotect (void *addr, size_t len, int prot)
+{
+ DWORD old_prot;
+ DWORD new_prot = 0;
+
+ syscall_printf ("mprotect (addr %x, len %u, prot %x)", addr, len, prot);
+
+ if (!wincap.virtual_protect_works_on_shared_pages ()
+ && addr >= (caddr_t)0x80000000 && addr <= (caddr_t)0xBFFFFFFF)
+ {
+ syscall_printf ("0 = mprotect (9x: No VirtualProtect on shared memory)");
+ return 0;
+ }
+
+ switch (prot)
+ {
+ case PROT_READ | PROT_WRITE | PROT_EXEC:
+ case PROT_WRITE | PROT_EXEC:
+ new_prot = PAGE_EXECUTE_READWRITE;
+ break;
+ case PROT_READ | PROT_WRITE:
+ case PROT_WRITE:
+ new_prot = PAGE_READWRITE;
+ break;
+ case PROT_READ | PROT_EXEC:
+ new_prot = PAGE_EXECUTE_READ;
+ break;
+ case PROT_READ:
+ new_prot = PAGE_READONLY;
+ break;
+ case PROT_EXEC:
+ new_prot = PAGE_EXECUTE;
+ break;
+ case PROT_NONE:
+ new_prot = PAGE_NOACCESS;
+ break;
+ default:
+ syscall_printf ("-1 = mprotect (): invalid prot value");
+ set_errno (EINVAL);
+ return -1;
+ }
+
+ if (VirtualProtect (addr, len, new_prot, &old_prot) == 0)
+ {
+ __seterrno ();
+ syscall_printf ("-1 = mprotect (): %E");
+ return -1;
+ }
+
+ syscall_printf ("0 = mprotect ()");
+ return 0;
+}
+
/*
* Base implementation:
*
@@ -900,62 +988,6 @@ fhandler_disk_file::fixup_mmap_after_fork (HANDLE h, DWORD access, DWORD offset,
return base == address;
}
-/* Set memory protection */
-
-extern "C" int
-mprotect (caddr_t addr, size_t len, int prot)
-{
- DWORD old_prot;
- DWORD new_prot = 0;
-
- syscall_printf ("mprotect (addr %x, len %u, prot %x)", addr, len, prot);
-
- if (!wincap.virtual_protect_works_on_shared_pages ()
- && addr >= (caddr_t)0x80000000 && addr <= (caddr_t)0xBFFFFFFF)
- {
- syscall_printf ("0 = mprotect (9x: No VirtualProtect on shared memory)");
- return 0;
- }
-
- switch (prot)
- {
- case PROT_READ | PROT_WRITE | PROT_EXEC:
- case PROT_WRITE | PROT_EXEC:
- new_prot = PAGE_EXECUTE_READWRITE;
- break;
- case PROT_READ | PROT_WRITE:
- case PROT_WRITE:
- new_prot = PAGE_READWRITE;
- break;
- case PROT_READ | PROT_EXEC:
- new_prot = PAGE_EXECUTE_READ;
- break;
- case PROT_READ:
- new_prot = PAGE_READONLY;
- break;
- case PROT_EXEC:
- new_prot = PAGE_EXECUTE;
- break;
- case PROT_NONE:
- new_prot = PAGE_NOACCESS;
- break;
- default:
- syscall_printf ("-1 = mprotect (): invalid prot value");
- set_errno (EINVAL);
- return -1;
- }
-
- if (VirtualProtect (addr, len, new_prot, &old_prot) == 0)
- {
- __seterrno ();
- syscall_printf ("-1 = mprotect (): %E");
- return -1;
- }
-
- syscall_printf ("0 = mprotect ()");
- return 0;
-}
-
/*
* Call to re-create all the file mappings in a forked
* child. Called from the child in initialization. At this
@@ -976,94 +1008,94 @@ fixup_mmaps_after_fork (HANDLE parent)
return 0;
/* Iterate through the map */
- for (int it = 0; it < mmapped_areas->nlists; ++it)
+ list *map_list;
+ for (int list_idx = 0;
+ (map_list = mmapped_areas->get_list (list_idx));
+ ++list_idx)
{
- list *map_list = mmapped_areas->lists[it];
- if (map_list)
+ mmap_record *rec;
+ for (int record_idx = 0;
+ (rec = map_list->get_record (record_idx));
+ ++record_idx)
{
- int li;
- for (li = 0; li < map_list->nrecs; ++li)
- {
- mmap_record *rec = map_list->recs + li;
-
- debug_printf ("fd %d, h %x, access %x, offset %D, size %u, address %p",
- rec->get_fd (), rec->get_handle (), rec->get_access (),
- rec->get_offset (), rec->get_size (), rec->get_address ());
- fhandler_base *fh = rec->alloc_fh ();
- BOOL ret = fh->fixup_mmap_after_fork (rec->get_handle (),
- rec->get_access (),
- rec->get_offset (),
- rec->get_size (),
- rec->get_address ());
- rec->free_fh (fh);
-
- if (!ret)
- return -1;
- if (rec->get_access () == FILE_MAP_COPY)
- {
- for (char *address = rec->get_address ();
- address < rec->get_address () + rec->get_size ();
- address += getpagesize ())
- if (rec->access (address)
- && !ReadProcessMemory (parent, address, address,
- getpagesize (), NULL))
+ debug_printf ("fd %d, h %x, access %x, offset %D, size %u, address %p",
+ rec->get_fd (), rec->get_handle (), rec->get_access (),
+ rec->get_offset (), rec->get_size (), rec->get_address ());
+
+ fhandler_base *fh = rec->alloc_fh ();
+ BOOL ret = fh->fixup_mmap_after_fork (rec->get_handle (),
+ rec->get_access (),
+ rec->get_offset (),
+ rec->get_size (),
+ rec->get_address ());
+ rec->free_fh (fh);
+
+ if (!ret)
+ return -1;
+ if (rec->get_access () == FILE_MAP_COPY)
+ {
+ for (char *address = rec->get_address ();
+ address < rec->get_address () + rec->get_size ();
+ address += getpagesize ())
+ if (rec->access (address)
+ && !ReadProcessMemory (parent, address, address,
+ getpagesize (), NULL))
+ {
+ DWORD old_prot;
+ DWORD last_error = GetLastError ();
+
+ if (last_error != ERROR_PARTIAL_COPY
+ && last_error != ERROR_NOACCESS
+ || !wincap.virtual_protect_works_on_shared_pages ())
{
- DWORD old_prot;
- DWORD last_error = GetLastError ();
-
- if (last_error != ERROR_PARTIAL_COPY
- && last_error != ERROR_NOACCESS
- || !wincap.virtual_protect_works_on_shared_pages ())
- {
- system_printf ("ReadProcessMemory failed for "
- "MAP_PRIVATE address %p, %E",
- rec->get_address ());
- return -1;
- }
- if (!VirtualProtectEx (parent,
- address, getpagesize (),
- PAGE_READONLY, &old_prot))
+ system_printf ("ReadProcessMemory failed for "
+ "MAP_PRIVATE address %p, %E",
+ rec->get_address ());
+ return -1;
+ }
+ if (!VirtualProtectEx (parent,
+ address, getpagesize (),
+ PAGE_READONLY, &old_prot))
+ {
+ system_printf ("VirtualProtectEx failed for "
+ "MAP_PRIVATE address %p, %E",
+ rec->get_address ());
+ return -1;
+ }
+ else
+ {
+ BOOL ret;
+ DWORD dummy_prot;
+
+ ret = ReadProcessMemory (parent, address, address,
+ getpagesize (), NULL);
+ if (!VirtualProtectEx(parent,
+ address, getpagesize (),
+ old_prot, &dummy_prot))
+ system_printf ("WARNING: VirtualProtectEx to "
+ "return to previous state "
+ "in parent failed for "
+ "MAP_PRIVATE address %p, %E",
+ rec->get_address ());
+ if (!VirtualProtect (address, getpagesize (),
+ old_prot, &dummy_prot))
+ system_printf ("WARNING: VirtualProtect to copy "
+ "protection to child failed for"
+ "MAP_PRIVATE address %p, %E",
+ rec->get_address ());
+ if (!ret)
{
- system_printf ("VirtualProtectEx failed for "
+ system_printf ("ReadProcessMemory (2nd try) "
+ "failed for "
"MAP_PRIVATE address %p, %E",
rec->get_address ());
return -1;
}
- else
- {
- BOOL ret;
- DWORD dummy_prot;
-
- ret = ReadProcessMemory (parent, address, address,
- getpagesize (), NULL);
- if (!VirtualProtectEx(parent,
- address, getpagesize (),
- old_prot, &dummy_prot))
- system_printf ("WARNING: VirtualProtectEx to "
- "return to previous state "
- "in parent failed for "
- "MAP_PRIVATE address %p, %E",
- rec->get_address ());
- if (!VirtualProtect (address, getpagesize (),
- old_prot, &dummy_prot))
- system_printf ("WARNING: VirtualProtect to copy "
- "protection to child failed for"
- "MAP_PRIVATE address %p, %E",
- rec->get_address ());
- if (!ret)
- {
- system_printf ("ReadProcessMemory (2nd try) "
- "failed for "
- "MAP_PRIVATE address %p, %E",
- rec->get_address ());
- return -1;
- }
- }
}
- }
- rec->fixup_map ();
+ }
}
+ rec->fixup_page_map ();
}
}
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc
index 01e9a6ba163..0c66d993d52 100644
--- a/winsup/cygwin/passwd.cc
+++ b/winsup/cygwin/passwd.cc
@@ -183,6 +183,7 @@ getpwuid_r32 (__uid32_t uid, struct passwd *pwd, char *buffer, size_t bufsize, s
pwd->pw_dir = pwd->pw_name + strlen (temppw->pw_name) + 1;
pwd->pw_shell = pwd->pw_dir + strlen (temppw->pw_dir) + 1;
pwd->pw_gecos = pwd->pw_shell + strlen (temppw->pw_shell) + 1;
+ pwd->pw_comment = NULL;
pwd->pw_passwd = pwd->pw_gecos + strlen (temppw->pw_gecos) + 1;
strcpy (pwd->pw_name, temppw->pw_name);
strcpy (pwd->pw_dir, temppw->pw_dir);
@@ -240,6 +241,7 @@ getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, s
pwd->pw_dir = pwd->pw_name + strlen (temppw->pw_name) + 1;
pwd->pw_shell = pwd->pw_dir + strlen (temppw->pw_dir) + 1;
pwd->pw_gecos = pwd->pw_shell + strlen (temppw->pw_shell) + 1;
+ pwd->pw_comment = NULL;
pwd->pw_passwd = pwd->pw_gecos + strlen (temppw->pw_gecos) + 1;
strcpy (pwd->pw_name, temppw->pw_name);
strcpy (pwd->pw_dir, temppw->pw_dir);
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index ca8f207f77e..79b521bc1f1 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -3486,6 +3486,10 @@ conv_path_list_buf_size (const char *path_list, bool to_posix)
+ (num_elms * max_mount_path_len)
+ (nrel * strlen (to_posix ? pc.normalized_path : pc.get_win32 ()))
+ 100;
+
+ cfree (pc.normalized_path); // FIXME - probably should be in a destructor but
+ // it's hard to justify a destructor for the few
+ // places where this is needed
return size;
}
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 9cb06c48cd6..61ed29d1588 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -292,18 +292,27 @@ _pinfo::commune_recv ()
{
unsigned n = 1;
CloseHandle (__fromthem); __fromthem = NULL;
- for (char **a = __argv; *a; a++)
- n += strlen (*a) + 1;
+ extern int __argc_safe;
+ const char *argv[__argc_safe + 1];
+ for (int i = 0; i < __argc_safe; i++)
+ {
+ if (IsBadStringPtr (__argv[i], 0x7fffffff))
+ 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 (char **a = __argv; *a; a++)
+ 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);
+ sigproc_printf ("WriteFile arg %d failed, %E", a - argv);
break;
}
if (!WriteFile (__tothem, "", 1, &nr, NULL))
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index 030c7e91b43..9bdcb71c000 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -12,14 +12,6 @@ details. */
#define _PINFO_H
/* Signal constants (have to define them here, unfortunately) */
-enum
-{
- __SIGFLUSH = -2,
- __SIGSTRACE = -1,
- __SIGCOMMUNE = 0,
- __SIGOFFSET = 2
-};
-
#define PSIZE 63
#include <sys/resource.h>
@@ -119,24 +111,19 @@ public:
inline sigset_t& getsigmask ()
{
- return thread2signal ? *thread2signal->sigmask : sig_mask;
+ return sig_mask;
}
inline void setsigmask (sigset_t mask)
{
- if (thread2signal)
- *(thread2signal->sigmask) = mask;
sig_mask = mask;
}
- inline LONG* getsigtodo (int sig) {return _sigtodo + __SIGOFFSET + sig;}
-
inline HANDLE getthread2signal ()
{
- return thread2signal ? thread2signal->win32_obj_id : hMainThread;
+ return hMainThread;
}
- inline void setthread2signal (void *thr) {thread2signal = (pthread *) thr;}
void commune_recv ();
commune_result commune_send (DWORD, ...);
bool alive ();
@@ -144,10 +131,10 @@ public:
friend void __stdcall set_myself (pid_t, HANDLE);
+ /* signals */
+ HANDLE sendsig;
private:
- sigset_t sig_mask; /* one set for everything to ignore. */
- LONG _sigtodo[NSIG + __SIGOFFSET];
- pthread *thread2signal; // NULL means thread any other means a pthread
+ sigset_t sig_mask;
CRITICAL_SECTION lock;
};
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index a1e99b27e25..242556ad6c4 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -76,7 +76,7 @@ fhandler_pipe::read (void *in_ptr, size_t& in_len)
ResetEvent (read_state);
cygthread *th = new cygthread (read_pipe, &pi, "read_pipe");
if (th->detach (read_state) && !in_len)
- (ssize_t) in_len = -1; /* received a signal */
+ in_len = (size_t) -1; /* received a signal */
}
(void) ReleaseMutex (guard);
return;
diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc
index 1f1145840fa..997e0f622cd 100644
--- a/winsup/cygwin/shared.cc
+++ b/winsup/cygwin/shared.cc
@@ -145,24 +145,40 @@ open_shared (const char *name, int n, HANDLE &shared_h, DWORD size, shared_locat
}
void
-shared_info::initialize ()
+shared_info::initialize (const char *user_name)
{
- if (version)
+ DWORD sversion = (DWORD) InterlockedExchange ((LONG *) &version, SHARED_VERSION_MAGIC);
+ if (!sversion)
+ {
+ /* Initialize the queue of deleted files. */
+ delqueue.init ();
+
+ /* Initialize tty table. */
+ tty.init ();
+ }
+ else
{
if (version != SHARED_VERSION_MAGIC)
- multiple_cygwin_problem ("shared", version, SHARED_VERSION_MAGIC);
- else if (cb != SHARED_INFO_CB)
- multiple_cygwin_problem ("shared size", cb, SHARED_INFO_CB);
- return;
+ {
+ multiple_cygwin_problem ("shared", version, SHARED_VERSION_MAGIC);
+ InterlockedExchange ((LONG *) &version, sversion);
+ }
+ while (!cb)
+ low_priority_sleep (0); // Should be hit only very very rarely
+ }
+
+ /* Initialize the Cygwin heap, if necessary */
+ if (!cygheap)
+ {
+ cygheap_init ();
+ cygheap->user.set_name (user_name);
}
- /* Initialize the queue of deleted files. */
- delqueue.init ();
+ heap_init ();
+
+ if (!sversion)
+ cb = sizeof (*this); // Do last, after all shared memory initializion
- /* Initialize tty table. */
- tty.init ();
- version = SHARED_VERSION_MAGIC;
- cb = sizeof (*this);
if (cb != SHARED_INFO_CB)
system_printf ("size of shared memory region changed from %u to %u",
SHARED_INFO_CB, cb);
@@ -172,6 +188,13 @@ void __stdcall
memory_init ()
{
getpagesize ();
+
+ char user_name[UNLEN + 1];
+ DWORD user_name_len = UNLEN + 1;
+
+ if (!GetUserName (user_name, &user_name_len))
+ strcpy (user_name, "unknown");
+
/* Initialize general shared memory */
HANDLE shared_h = cygheap ? cygheap->shared_h : NULL;
cygwin_shared = (shared_info *) open_shared ("shared",
@@ -180,27 +203,12 @@ memory_init ()
sizeof (*cygwin_shared),
SH_CYGWIN_SHARED);
- cygwin_shared->initialize ();
-
- /* Allocate memory for the per-user mount table */
- char user_name[UNLEN + 1];
- DWORD user_name_len = UNLEN + 1;
-
- if (!GetUserName (user_name, &user_name_len))
- strcpy (user_name, "unknown");
-
- /* Initialize the Cygwin heap, if necessary */
- if (!cygheap)
- {
- cygheap_init ();
- cygheap->user.set_name (user_name);
- }
+ cygwin_shared->initialize (user_name);
cygheap->shared_h = shared_h;
ProtectHandleINH (cygheap->shared_h);
- heap_init ();
-
+ /* Allocate memory for the per-user mount table */
mount_table = (mount_info *) open_shared (user_name, MOUNT_VERSION,
cygwin_mount_h, sizeof (mount_info),
SH_MOUNT_TABLE);
diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h
index 7014c56daff..b11ecb3ac76 100644
--- a/winsup/cygwin/shared_info.h
+++ b/winsup/cygwin/shared_info.h
@@ -141,7 +141,7 @@ public:
#define SHARED_INFO_CB 47112
-#define CURR_SHARED_MAGIC 0x359218a2U
+#define CURR_SHARED_MAGIC 0x53f1a7f4U
/* NOTE: Do not make gratuitous changes to the names or organization of the
below class. The layout is checksummed to determine compatibility between
@@ -156,7 +156,7 @@ class shared_info
tty_list tty;
delqueue_list delqueue;
- void initialize ();
+ void initialize (const char *);
unsigned heap_chunk_size ();
};
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
index 2b890dd624f..a85e151d988 100644
--- a/winsup/cygwin/signal.cc
+++ b/winsup/cygwin/signal.cc
@@ -17,6 +17,7 @@ details. */
#include <sys/cygwin.h>
#include "sigproc.h"
#include "pinfo.h"
+#include "hires.h"
int sigcatchers; /* FIXME: Not thread safe. */
@@ -73,20 +74,22 @@ nanosleep (const struct timespec *rqtp, struct timespec *rmtp)
sigframe thisframe (mainthread);
pthread_testcancel ();
- if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec > 999999999)
+ if ((unsigned int) rqtp->tv_sec > (HIRES_DELAY_MAX / 1000 - 1)
+ || (unsigned int) rqtp->tv_nsec > 999999999)
{
set_errno (EINVAL);
return -1;
}
-
- DWORD req = rqtp->tv_sec * 1000 + (rqtp->tv_nsec + 500000) / 1000000;
- DWORD start_time = GetTickCount ();
- DWORD end_time = start_time + req;
+ DWORD resolution = gtod.resolution ();
+ DWORD req = ((rqtp->tv_sec * 1000 + (rqtp->tv_nsec + 999999) / 1000000
+ + resolution - 1) / resolution ) * resolution;
+ DWORD end_time = gtod.dmsecs () + req;
syscall_printf ("nanosleep (%ld)", req);
int rc = pthread::cancelable_wait (signal_arrived, req);
- DWORD now = GetTickCount ();
- DWORD rem = (rc == WAIT_TIMEOUT || now >= end_time) ? 0 : end_time - now;
+ DWORD rem;
+ if ((rem = end_time - gtod.dmsecs ()) > HIRES_DELAY_MAX)
+ rem = 0;
if (rc == WAIT_OBJECT_0)
{
(void) thisframe.call_signal_handler ();
@@ -111,7 +114,7 @@ sleep (unsigned int seconds)
req.tv_sec = seconds;
req.tv_nsec = 0;
nanosleep (&req, &rem);
- return rem.tv_sec + (rem.tv_nsec + 500000000) / 1000000000;
+ return rem.tv_sec + (rem.tv_nsec > 0);
}
extern "C" unsigned int
@@ -179,8 +182,6 @@ kill_worker (pid_t pid, int sig)
return -1;
}
- dest->setthread2signal (NULL);
-
if ((sendSIGCONT = (sig < 0)))
sig = -sig;
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 6ce58fed804..12ef3be144c 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -28,7 +28,6 @@ details. */
#include "dtable.h"
#include "cygheap.h"
#include "child_info_magic.h"
-#define NEED_VFORK
#include "perthread.h"
#include "shared_info.h"
#include "cygthread.h"
@@ -49,14 +48,33 @@ details. */
#define NZOMBIES 256
-static LONG local_sigtodo[TOTSIGS];
-struct sigaction *global_sigs;
+class sigelem
+{
+ int sig;
+ class sigelem *next;
+ friend class pending_signals;
+ friend int __stdcall sig_dispatch_pending ();
+};
-inline LONG *
-getlocal_sigtodo (int sig)
+class pending_signals
{
- return local_sigtodo + __SIGOFFSET + sig;
-}
+ sigelem sigs[NSIG + 1];
+ sigelem start;
+ sigelem *end;
+ sigelem *prev;
+ sigelem *curr;
+ int empty;
+public:
+ void reset () {curr = &start; prev = &start;}
+ void add (int sig);
+ void del ();
+ int next ();
+ friend int __stdcall sig_dispatch_pending ();
+};
+
+static pending_signals sigqueue;
+
+struct sigaction *global_sigs;
void __stdcall
sigalloc ()
@@ -107,20 +125,9 @@ HANDLE NO_COPY signal_arrived; // Event signaled when a signal has
Static DWORD proc_loop_wait = 1000; // Wait for subprocesses to exit
Static DWORD sig_loop_wait = INFINITE; // Wait for signals to arrive
-Static HANDLE sigcatch_nonmain; // The semaphore signaled when
- // signals are available for
- // processing from non-main thread
-Static HANDLE sigcatch_main; // Signalled when main thread sends a
- // signal
-Static HANDLE sigcatch_nosync; // Signal wait_sig to scan sigtodo
- // but not to bother with any
- // synchronization
Static HANDLE sigcomplete_main; // Event signaled when a signal has
// finished processing for the main
// thread
-Static HANDLE sigcomplete_nonmain; // Semaphore raised for non-main
- // threads when a signal has finished
- // processing
HANDLE NO_COPY sigCONT; // Used to "STOP" a process
Static cygthread *hwait_sig; // Handle of wait_sig thread
Static cygthread *hwait_subproc; // Handle of sig_subproc thread
@@ -147,13 +154,10 @@ muto NO_COPY *sync_proc_subproc = NULL; // Control access to subproc stuff
DWORD NO_COPY sigtid = 0; // ID of the signal thread
-static bool NO_COPY pending_signals = false; // true if signals pending
-
/* Functions
*/
static int __stdcall checkstate (waitq *) __attribute__ ((regparm (1)));
static __inline__ BOOL get_proc_lock (DWORD, DWORD);
-static HANDLE __stdcall getevent (_pinfo *, const char *) __attribute__ ((regparm (2)));
static void __stdcall remove_zombie (int);
static DWORD WINAPI wait_sig (VOID *arg);
static int __stdcall stopped_or_terminated (waitq *, _pinfo *);
@@ -201,7 +205,6 @@ wait_for_sigthread ()
{
sigproc_printf ("wait_sig_inited %p", wait_sig_inited);
HANDLE hsig_inited = wait_sig_inited;
- assert (hsig_inited);
(void) WaitForSingleObject (hsig_inited, INFINITE);
wait_sig_inited = NULL;
(void) ForceCloseHandle1 (hsig_inited, wait_sig_inited);
@@ -531,56 +534,45 @@ proc_terminate (void)
sigproc_printf ("leaving");
}
-/* Clear pending signal from the sigtodo array
- */
+/* Clear pending signal */
void __stdcall
-sig_clear (int sig)
+sig_clear (int target_sig)
{
- (void) InterlockedExchange (myself->getsigtodo (sig), 0L);
- (void) InterlockedExchange (getlocal_sigtodo (sig), 0L);
+ if (GetCurrentThreadId () != sigtid)
+ sig_send (myself, -target_sig);
+ else
+ {
+ int sig;
+ sigqueue.reset ();
+ while ((sig = sigqueue.next ()))
+ if (sig == target_sig)
+ {
+ sigqueue.del ();
+ break;
+ }
+ }
return;
}
extern "C" int
-sigpending (sigset_t *set)
+sigpending (sigset_t *mask)
{
- unsigned bit;
- *set = 0;
- for (int sig = 1; sig < NSIG; sig++)
- if ((*getlocal_sigtodo (sig) || *myself->getsigtodo (sig))
- && (myself->getsigmask () & (bit = SIGTOMASK (sig))))
- *set |= bit;
+ sigset_t outset = (sigset_t) sig_send (myself, __SIGPENDING);
+ if (outset == SIG_BAD_MASK)
+ return -1;
+ *mask = outset;
return 0;
}
-/* Force the wait_sig thread to wake up and scan the sigtodo array.
- */
-extern "C" int __stdcall
+/* Force the wait_sig thread to wake up and scan for pending signals */
+int __stdcall
sig_dispatch_pending ()
{
- if (!hwait_sig || GetCurrentThreadId () == sigtid)
+ if (!hwait_sig || GetCurrentThreadId () == sigtid || !sigqueue.start.next)
return 0;
sigframe thisframe (mainthread);
-
-#ifdef DEBUGGING
- sigproc_printf ("pending_signals %d", pending_signals);
-#endif
-
- if (!pending_signals)
-#ifdef DEBUGGING
- sigproc_printf ("no need to wake anything up");
-#else
- ;
-#endif
- else
- {
- (void) sig_send (myself, __SIGFLUSH);
-#ifdef DEBUGGING
- sigproc_printf ("woke up wait_sig");
-#endif
- }
-
+ (void) sig_send (myself, __SIGFLUSH);
return thisframe.call_signal_handler ();
}
@@ -642,12 +634,7 @@ sigproc_terminate (void)
sig_loop_wait = 0; // Tell wait_sig to exit when it is
// finished with anything it is doing
ForceCloseHandle (sigcomplete_main);
- for (int i = 0; i < 20; i++)
- (void) ReleaseSemaphore (sigcomplete_nonmain, 1, NULL);
- // ForceCloseHandle (sigcomplete_nonmain);
- // ForceCloseHandle (sigcatch_main);
- // ForceCloseHandle (sigcatch_nonmain);
- // ForceCloseHandle (sigcatch_nosync);
+ CloseHandle (myself->sendsig);
}
proc_terminate (); // Terminate process handling thread
@@ -665,15 +652,15 @@ sig_send (_pinfo *p, int sig, DWORD ebp, bool exception)
int rc = 1;
DWORD tid = GetCurrentThreadId ();
BOOL its_me;
- HANDLE thiscatch = NULL;
HANDLE thiscomplete = NULL;
- BOOL wait_for_completion;
+ HANDLE sendsig;
+ bool wait_for_completion;
sigframe thisframe;
if (p == myself_nowait_nonmain)
p = (tid == mainthread.id) ? (_pinfo *) myself : myself_nowait;
if (!(its_me = (p == NULL || p == myself || p == myself_nowait)))
- wait_for_completion = FALSE;
+ wait_for_completion = false;
else
{
if (no_signals_available ())
@@ -697,74 +684,76 @@ sig_send (_pinfo *p, int sig, DWORD ebp, bool exception)
sigproc_printf ("pid %d, signal %d, its_me %d", p->pid, sig, its_me);
- LONG *todo;
- bool issem;
if (its_me)
{
- if (!wait_for_completion)
+ if (wait_for_completion)
{
- thiscatch = sigcatch_nosync;
- todo = myself->getsigtodo (sig);
- issem = false;
+ thisframe.set (mainthread, ebp, exception);
+ thiscomplete = sigcomplete_main;
}
- else if (tid != mainthread.id)
+ sendsig = myself->sendsig;
+ }
+ else
+ {
+ HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId);
+ if (!hp)
{
- thiscatch = sigcatch_nonmain;
- thiscomplete = sigcomplete_nonmain;
- todo = getlocal_sigtodo (sig);
- issem = true;
+ __seterrno ();
+ goto out;
}
- else
+ if (!DuplicateHandle (hp, p->sendsig, hMainProc, &sendsig, false, 0,
+ DUPLICATE_SAME_ACCESS) || !sendsig)
{
- thiscatch = sigcatch_main;
- thiscomplete = sigcomplete_main;
- thisframe.set (mainthread, ebp, exception);
- todo = getlocal_sigtodo (sig);
- issem = true;
+ __seterrno ();
+ goto out;
}
}
- else if ((thiscatch = getevent (p, "sigcatch")))
- {
- todo = p->getsigtodo (sig);
- issem = false;
- }
- else
- goto out; // Couldn't get the semaphore. getevent issued
- // an error, if appropriate.
-
-#if WHEN_MULTI_THREAD_SIGNALS_WORK
- signal_dispatch *sd;
- sd = signal_dispatch_storage.get ();
- if (sd == NULL)
- sd = signal_dispatch_storage.create ();
-#endif
- /* Increment the sigtodo array to signify which signal to assert.
- */
- (void) InterlockedIncrement (todo);
-
- /* Notify the process that a signal has arrived.
- */
- if (issem ? !ReleaseSemaphore (thiscatch, 1, NULL) : !SetEvent (thiscatch))
+ DWORD nb;
+ if (!WriteFile (sendsig, &sig, sizeof (sig), &nb, NULL) || nb != sizeof (sig))
{
/* Couldn't signal the semaphore. This probably means that the
* process is exiting.
*/
if (!its_me)
- ForceCloseHandle (thiscatch);
+ {
+ __seterrno ();
+ ForceCloseHandle (sendsig);
+ }
else
{
if (no_signals_available ())
sigproc_printf ("I'm going away now");
- else if ((int) GetLastError () == -1)
- rc = WaitForSingleObject (thiscomplete, 500);
else
- system_printf ("error sending signal %d to pid %d, semaphore %p, %E",
- sig, p->pid, thiscatch);
+ system_printf ("error sending signal %d to pid %d, pipe handle %p, %E",
+ sig, p->pid, sendsig);
}
goto out;
}
+ /* Write completion handle or NULL */
+ if (!WriteFile (sendsig, &thiscomplete, sizeof (thiscomplete), &nb, NULL)
+ || nb != sizeof (thiscomplete))
+ {
+ __seterrno ();
+ goto out;
+ }
+
+ sigset_t pending;
+ sigset_t *mask;
+ if (sig == __SIGPENDING)
+ mask = &pending;
+ else if (sig == __SIGFLUSH || sig > 0)
+ mask = &myself->getsigmask ();
+ else
+ mask = NULL;
+ if (mask && !WriteFile (sendsig, &mask, sizeof (mask), &nb, NULL)
+ || nb != sizeof (pending))
+ {
+ __seterrno ();
+ goto out;
+ }
+
/* No need to wait for signal completion unless this was a signal to
* this process.
*
@@ -777,7 +766,7 @@ sig_send (_pinfo *p, int sig, DWORD ebp, bool exception)
rc = WAIT_OBJECT_0;
sigproc_printf ("Not waiting for sigcomplete. its_me %d signal %d", its_me, sig);
if (!its_me)
- ForceCloseHandle (thiscatch);
+ ForceCloseHandle (sendsig);
}
else
{
@@ -798,19 +787,16 @@ sig_send (_pinfo *p, int sig, DWORD ebp, bool exception)
}
out:
- sigproc_printf ("returning %d from sending signal %d", rc, sig);
+ if (sig != __SIGPENDING)
+ /* nothing */;
+ else if (!rc)
+ rc = (int) pending;
+ else
+ rc = SIG_BAD_MASK;
+ sigproc_printf ("returning %p from sending signal %d", rc, sig);
return rc;
}
-/* Set pending signal from the sigtodo array
- */
-void __stdcall
-sig_set_pending (int sig)
-{
- (void) InterlockedIncrement (getlocal_sigtodo (sig));
- return;
-}
-
/* Initialize the wait_subproc thread.
* Called from fork() or spawn() to initialize the handling of subprocesses.
*/
@@ -892,71 +878,6 @@ out:
return potential_match;
}
-/* Get or create a process specific semaphore used in message passing.
- */
-static HANDLE __stdcall
-getevent (_pinfo *p, const char *str)
-{
- HANDLE h;
- char sem_name[MAX_PATH];
-
- if (p != NULL)
- {
- if (!proc_can_be_signalled (p))
- {
- set_errno (ESRCH);
- return NULL;
- }
- int wait = 1000;
- /* Wait for new process to generate its semaphores. */
- sigproc_printf ("pid %d, ppid %d, wait %d, initializing %x", p->pid, p->ppid, wait,
- ISSTATE (p, PID_INITIALIZING));
- for (int i = 0; ISSTATE (p, PID_INITIALIZING) && i < wait; i++)
- low_priority_sleep (1);
- }
-
- if (p == NULL)
- {
- char sa_buf[1024];
-
- DWORD winpid = GetCurrentProcessId ();
-#if 0
- h = CreateSemaphore (sec_user_nih (sa_buf), init, max,
- str = shared_name (sem_name, str, winpid));
-#else
- h = CreateEvent (sec_user_nih (sa_buf), FALSE, FALSE,
- str = shared_name (sem_name, str, winpid));
-#endif
- p = myself;
- if (!h)
- {
- system_printf ("can't create semaphore %s, %E", str);
- __seterrno ();
- }
- }
- else
- {
-#if 0
- h = OpenSemaphore (SEMAPHORE_ALL_ACCESS, FALSE,
- shared_name (sem_name, str, p->dwProcessId));
-#else
- h = OpenEvent (EVENT_ALL_ACCESS, FALSE,
- shared_name (sem_name, str, p->dwProcessId));
-#endif
-
- if (!h)
- {
- if (GetLastError () == ERROR_FILE_NOT_FOUND && !proc_exists (p))
- set_errno (ESRCH); /* No such process */
- else
- set_errno (EPERM); /* Couldn't access the semaphore --
- different cygwin DLL maybe? */
- }
- }
-
- return h;
-}
-
/* Remove a zombie from zombies by swapping it with the last child in the list.
*/
static void __stdcall
@@ -1058,62 +979,94 @@ talktome ()
pids[i]->commune_recv ();
}
-#define RC_MAIN 0
-#define RC_NONMAIN 1
-#define RC_NOSYNC 2
/* Process signals by waiting for a semaphore to become signaled.
- * Then scan an in-memory array representing queued signals.
- * Executes in a separate thread.
- *
- * Signals sent from this process are sent a completion signal so
- * that returns from kill/raise do not occur until the signal has
- * has been handled, as per POSIX.
- */
+ Then scan an in-memory array representing queued signals.
+ Executes in a separate thread.
+
+ Signals sent from this process are sent a completion signal so
+ that returns from kill/raise do not occur until the signal has
+ has been handled, as per POSIX. */
+
+void
+pending_signals::add (int sig)
+{
+ sigelem *se;
+ for (se = start.next; se; se = se->next)
+ if (se->sig == sig)
+ return;
+ while (sigs[empty].sig)
+ if (++empty == NSIG)
+ empty = 0;
+ se = sigs + empty;
+ se->sig = sig;
+ se->next = NULL;
+ if (end)
+ end->next = se;
+ end = se;
+ if (!start.next)
+ start.next = se;
+ empty++;
+}
+
+void
+pending_signals::del ()
+{
+ sigelem *next = curr->next;
+ prev->next = next;
+ curr->sig = 0;
+#ifdef DEBUGGING
+ curr->next = NULL;
+#endif
+ if (end == curr)
+ end = prev;
+ empty = curr - sigs;
+ curr = next;
+}
+
+int
+pending_signals::next ()
+{
+ int sig;
+ prev = curr;
+ if (!curr || !(curr = curr->next))
+ sig = 0;
+ else
+ sig = curr->sig;
+ return sig;
+}
+
+/* Process signals by waiting for signal data to arrive in a pipe.
+ Set a completion event if one was specified. */
static DWORD WINAPI
wait_sig (VOID *self)
{
- LONG *todos[] = {getlocal_sigtodo (0), myself->getsigtodo (0)};
+ HANDLE readsig;
+ char sa_buf[1024];
+
/* Initialization */
(void) SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY);
- /* sigcatch_nosync - semaphore incremented by sig_dispatch_pending and
- * by foreign processes to force an examination of
- * the sigtodo array.
- * sigcatch_main - ditto for local main thread.
- * sigcatch_nonmain - ditto for local non-main threads.
- *
- * sigcomplete_main - event used to signal main thread on signal
- * completion
- * sigcomplete_nonmain - semaphore signaled for non-main thread on signal
- * completion
- */
- sigcatch_nosync = getevent (NULL, "sigcatch");
- sigcatch_nonmain = CreateSemaphore (&sec_none_nih, 0, MAXLONG, NULL);
- sigcatch_main = CreateSemaphore (&sec_none_nih, 0, MAXLONG, NULL);
- sigcomplete_nonmain = CreateSemaphore (&sec_none_nih, 0, MAXLONG, NULL);
+ /* sigcomplete_main - event used to signal main thread on signal
+ completion */
+ if (!CreatePipe (&readsig, &myself->sendsig, sec_user_nih (sa_buf), 0))
+ api_fatal ("couldn't create signal pipe, %E");
sigcomplete_main = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
- sigproc_printf ("sigcatch_nonmain %p, sigcatch_main %p", sigcatch_nonmain, sigcatch_main);
+ sigproc_printf ("sigcomplete_main %p", sigcomplete_main);
sigCONT = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
/* Setting dwProcessId flags that this process is now capable of receiving
- * signals. Prior to this, dwProcessId was set to the windows pid of
- * of the original windows process which spawned us unless this was a
- * "toplevel" process.
- */
+ signals. Prior to this, dwProcessId was set to the windows pid of
+ of the original windows process which spawned us unless this was a
+ "toplevel" process. */
myself->dwProcessId = GetCurrentProcessId ();
myself->process_state |= PID_ACTIVE;
myself->process_state &= ~PID_INITIALIZING;
- ProtectHandle (sigcatch_nosync);
- ProtectHandle (sigcatch_nonmain);
- ProtectHandle (sigcatch_main);
- ProtectHandle (sigcomplete_nonmain);
ProtectHandle (sigcomplete_main);
/* If we've been execed, then there is still a stub left in the previous
- * windows process waiting to see if it's started a cygwin process or not.
- * Signalling subproc_ready indicates that we are a cygwin process.
- */
+ windows process waiting to see if it's started a cygwin process or not.
+ Signalling subproc_ready indicates that we are a cygwin process. */
if (child_proc_info && child_proc_info->type == PROC_EXEC)
{
debug_printf ("subproc_ready %p", child_proc_info->subproc_ready);
@@ -1130,149 +1083,82 @@ wait_sig (VOID *self)
SetEvent (wait_sig_inited);
sigtid = GetCurrentThreadId ();
- HANDLE catchem[] = {sigcatch_main, sigcatch_nonmain, sigcatch_nosync};
- sigproc_printf ("Ready. dwProcessid %d", myself->dwProcessId);
- DWORD rc = RC_NOSYNC;
- bool flush = false;
for (;;)
{
- DWORD i;
- if (rc == RC_MAIN || rc == RC_NONMAIN)
- i = RC_NOSYNC;
- else
- i = RC_MAIN;
- rc = WaitForSingleObject (catchem[i], 0);
- if (rc != WAIT_OBJECT_0)
- rc = WaitForMultipleObjects (3, catchem, FALSE, sig_loop_wait);
- else
- rc = i + WAIT_OBJECT_0;
- (void) SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY);
+ int sig;
+ DWORD nb;
+ if (!ReadFile (readsig, &sig, sizeof (sig), &nb, NULL))
+ break;
- /* sigproc_terminate sets sig_loop_wait to zero to indicate that
- this thread should terminate. */
- if (rc == WAIT_TIMEOUT)
+ HANDLE wakeup;
+ if (!ReadFile (readsig, &wakeup, sizeof (wakeup), &nb, NULL)
+ || nb != sizeof (wakeup))
{
- if (!sig_loop_wait)
- break; // Exiting
- else
- continue;
+ system_printf ("signal notification handle read failure, %E");
+ continue;
}
- if (rc == WAIT_FAILED)
+ if (!sig)
+ continue; /* Just checking to see if we exist */
+
+ sigset_t *mask;
+ if ((sig == __SIGFLUSH || sig == __SIGPENDING || sig > 0)
+ && (!ReadFile (readsig, &mask, sizeof (mask), &nb, NULL)
+ || nb != sizeof (mask)))
{
- if (sig_loop_wait != 0)
- system_printf ("WFMO failed, %E");
- break;
+ system_printf ("signal mask handle read failure, %E");
+ continue;
}
- rc -= WAIT_OBJECT_0;
- sigproc_printf ("awake, rc %d", rc);
- LONG *todo;
- if (rc != RC_NOSYNC)
- todo = todos[0];
- else
- todo = todos[1];
-
- /* A sigcatch semaphore has been signaled. Scan the sigtodo
- array looking for any unprocessed signals. */
- pending_signals = false;
- unsigned more_signals = 0;
- bool saw_failed_interrupt = false;
- do
+ switch (sig)
{
- more_signals = 0;
- for (int sig = -__SIGOFFSET; sig < NSIG; sig++)
+ case __SIGCOMMUNE:
+ talktome ();
+ continue;
+ case __SIGSTRACE:
+ strace.hello ();
+ continue;
+ case __SIGPENDING:
+ *mask = 0;
+ unsigned bit;
+ sigqueue.reset ();
+ while ((sig = sigqueue.next ()))
+ if (myself->getsigmask () & (bit = SIGTOMASK (sig)))
+ *mask |= bit;
+ break;
+ default:
+ if (sig > 0)
{
- LONG x = InterlockedDecrement (todo + sig);
- if (x < 0)
- InterlockedIncrement (todo + sig);
- else if (x >= 0)
- {
- /* If x > 0, we have to deal with a signal at some later point */
- if (rc != RC_NOSYNC && x > 0)
- pending_signals = true; // There should be an armed semaphore, in this case
-
- if (sig > 0 && sig != SIGKILL && sig != SIGSTOP &&
- (sigismember (&myself->getsigmask (), sig) ||
- main_vfork->pid ||
- (sig != SIGCONT && ISSTATE (myself, PID_STOPPED))))
- {
- sigproc_printf ("signal %d blocked", sig);
- x = InterlockedIncrement (myself->getsigtodo (sig));
- pending_signals = true;
- }
- else
- {
- sigproc_printf ("processing signal %d", sig);
- switch (sig)
- {
- case __SIGFLUSH:
- if (rc == RC_MAIN)
- {
- flush = true;
- SetEvent (sigcatch_nosync);
- goto out1;
- }
- break;
-
- /* Internal signal to turn on stracing. */
- case __SIGSTRACE:
- strace.hello ();
- break;
-
- case __SIGCOMMUNE:
- talktome ();
- break;
-
- /* A normal UNIX signal */
- default:
- sigproc_printf ("Got signal %d", sig);
- if (!sig_handle (sig))
- {
- saw_failed_interrupt = true;
- x = InterlockedIncrement (myself->getsigtodo (sig));
- pending_signals = true;
- }
- }
- if (rc == RC_NOSYNC && x > 0)
- more_signals++;
- }
-
- if (sig == SIGCHLD)
- proc_subproc (PROC_CLEARWAIT, 0);
-
- /* Need to take special action if an interrupt failed due to main thread not
- getting around to calling handler yet. */
- if (saw_failed_interrupt || rc != RC_NOSYNC)
- goto out;
- }
+ int sh;
+ for (int i = 0; !(sh = sig_handle (sig, *mask)) && i < 100 ; i++)
+ low_priority_sleep (0); // hopefully a temporary condition
+ if (sh <= 0)
+{if (!sh) small_printf ("*********sh == 0\n");
+ sigqueue.add (sig); // FIXME: Shouldn't add this in !sh condition
+}
+ if (sig == SIGCHLD)
+ proc_subproc (PROC_CLEARWAIT, 0);
}
-#ifdef DEBUGGING
- if (more_signals > 100)
- system_printf ("hmm. infinite loop? more_signals %u\n", more_signals);
-#endif
- }
- while (more_signals && sig_loop_wait);
-
- out:
- /* Signal completion of signal handling depending on which semaphore
- woke up the WaitForMultipleObjects above. */
- if (rc == RC_NONMAIN) // FIXME: This is broken
- ReleaseSemaphore (sigcomplete_nonmain, 1, NULL);
- else if (rc == RC_MAIN || flush)
- {
- SetEvent (sigcomplete_main);
- sigproc_printf ("set main thread completion event");
- flush = false;
- }
-
- out1:
- if (saw_failed_interrupt)
- {
- SetEvent (sigcatch_nosync);
- low_priority_sleep (0); /* Hopefully, other thread will be waking up soon. */
+ else
+ {
+ int target_sig = -sig;
+ sigqueue.reset ();
+ while ((sig = sigqueue.next ()))
+ if (sig == target_sig)
+ {
+ sigqueue.del ();
+ break;
+ }
+ }
+ case __SIGFLUSH:
+ sigqueue.reset ();
+ while ((sig = sigqueue.next ()))
+ if (sig_handle (sig, *mask) > 0)
+ sigqueue.del ();
+ break;
}
- sigproc_printf ("looping");
+ if (wakeup)
+ SetEvent (wakeup);
}
sigproc_printf ("done");
diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h
index 360ae8bcba3..4bc9615ce4a 100644
--- a/winsup/cygwin/sigproc.h
+++ b/winsup/cygwin/sigproc.h
@@ -16,6 +16,18 @@ details. */
#define EXIT_REPARENTING 0x020000
#define EXIT_NOCLOSEALL 0x040000
+#ifdef NSIG
+enum
+{
+ __SIGFLUSH = -(NSIG + 1),
+ __SIGSTRACE = -(NSIG + 2),
+ __SIGCOMMUNE = -(NSIG + 3),
+ __SIGPENDING = -(NSIG + 4)
+};
+#endif
+
+#define SIG_BAD_MASK (1 << (SIGKILL - 1))
+
enum procstuff
{
PROC_ADDCHILD = 1, // add a new subprocess to list
@@ -75,10 +87,10 @@ public:
if (!oframe)
t.get_winapi_lock ();
}
- inline void init (sigthread &t, DWORD ebp = (DWORD) __builtin_frame_address (0))
+ inline void init (sigthread &t, DWORD ebp = (DWORD) __builtin_frame_address (0), bool is_exception = 0)
{
- if (!t.frame && t.id == GetCurrentThreadId ())
- set (t, ebp);
+ if (is_exception || (!t.frame && t.id == GetCurrentThreadId ()))
+ set (t, ebp, is_exception);
else
st = NULL;
}
@@ -98,10 +110,10 @@ extern HANDLE signal_arrived;
extern HANDLE sigCONT;
BOOL __stdcall my_parent_is_alive ();
-extern "C" int __stdcall sig_dispatch_pending ();
+int __stdcall sig_dispatch_pending ();
extern "C" void __stdcall set_process_mask (sigset_t newmask);
extern "C" void __stdcall reset_signal_arrived ();
-int __stdcall sig_handle (int) __attribute__ ((regparm (1)));
+int __stdcall sig_handle (int, sigset_t) __attribute__ ((regparm (2)));
void __stdcall sig_clear (int) __attribute__ ((regparm (1)));
void __stdcall sig_set_pending (int) __attribute__ ((regparm (1)));
int __stdcall handle_sigsuspend (sigset_t);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 4fd7e7aea64..a3d7a81558e 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -30,6 +30,8 @@ details. */
#include <process.h>
#include <utmp.h>
#include <sys/uio.h>
+#include <errno.h>
+#include <ctype.h>
#include <limits.h>
#include <unistd.h>
#include <setjmp.h>
@@ -2427,6 +2429,8 @@ chroot (const char *newroot)
syscall_printf ("%d = chroot (%s)", ret ? get_errno () : 0,
newroot ? newroot : "NULL");
+ if (path.normalized_path)
+ cfree (path.normalized_path);
return ret;
}
@@ -2594,21 +2598,18 @@ ffs (int i)
}
extern "C" void
-login (struct utmp *ut)
+updwtmp (const char *wtmp_file, const struct utmp *ut)
{
- sigframe thisframe (mainthread);
- register int fd;
-
- pututline (ut);
- endutent ();
/* Writing to wtmp must be atomic to prevent mixed up data. */
char mutex_name[MAX_PATH];
- HANDLE mutex = CreateMutex (NULL, FALSE,
- shared_name (mutex_name, "wtmp_mutex", 0));
+ HANDLE mutex;
+ int fd;
+
+ mutex = CreateMutex (NULL, FALSE, shared_name (mutex_name, "wtmp_mutex", 0));
if (mutex)
while (WaitForSingleObject (mutex, INFINITE) == WAIT_ABANDONED)
;
- if ((fd = open (_PATH_WTMP, O_WRONLY | O_APPEND | O_BINARY, 0)) >= 0)
+ if ((fd = open (wtmp_file, O_WRONLY | O_APPEND | O_BINARY, 0)) >= 0)
{
write (fd, ut, sizeof *ut);
close (fd);
@@ -2620,6 +2621,33 @@ login (struct utmp *ut)
}
}
+extern "C" void
+logwtmp (const char *line, const char *user, const char *host)
+{
+ sigframe thisframe (mainthread);
+ struct utmp ut;
+ memset (&ut, 0, sizeof ut);
+ ut.ut_type = USER_PROCESS;
+ ut.ut_pid = getpid ();
+ if (line)
+ strncpy (ut.ut_line, line, sizeof ut.ut_line);
+ time (&ut.ut_time);
+ if (user)
+ strncpy (ut.ut_user, user, sizeof ut.ut_user);
+ if (host)
+ strncpy (ut.ut_host, host, sizeof ut.ut_host);
+ updwtmp (_PATH_WTMP, &ut);
+}
+
+extern "C" void
+login (struct utmp *ut)
+{
+ sigframe thisframe (mainthread);
+ pututline (ut);
+ endutent ();
+ updwtmp (_PATH_WTMP, ut);
+}
+
extern "C" int
logout (char *line)
{
@@ -2633,29 +2661,11 @@ logout (char *line)
if (ut)
{
- int fd;
-
ut->ut_type = DEAD_PROCESS;
memset (ut->ut_user, 0, sizeof ut->ut_user);
time (&ut->ut_time);
- /* Writing to wtmp must be atomic to prevent mixed up data. */
- char mutex_name[MAX_PATH];
- HANDLE mutex = CreateMutex (NULL, FALSE,
- shared_name (mutex_name, "wtmp_mutex", 0));
- if (mutex)
- while (WaitForSingleObject (mutex, INFINITE) == WAIT_ABANDONED)
- ;
- if ((fd = open (_PATH_WTMP, O_WRONLY | O_APPEND | O_BINARY, 0)) >= 0)
- {
- write (fd, &ut_buf, sizeof ut_buf);
- debug_printf ("set logout time for %s", line);
- close (fd);
- }
- if (mutex)
- {
- ReleaseMutex (mutex);
- CloseHandle (mutex);
- }
+ updwtmp (_PATH_WTMP, &ut_buf);
+ debug_printf ("set logout time for %s", line);
memset (ut->ut_line, 0, sizeof ut_buf.ut_line);
ut->ut_time = 0;
pututline (ut);
@@ -2962,3 +2972,67 @@ long gethostid(void)
return hostid;
}
+
+#define ETC_SHELLS "/etc/shells"
+static int shell_index;
+static FILE *shell_fp;
+
+extern "C" char *
+getusershell ()
+{
+ /* List of default shells if no /etc/shells exists, defined as on Linux.
+ FIXME: SunOS has a far longer list, containing all shells which
+ might be shipped with the OS. Should we do the same for the Cygwin
+ distro, adding bash, tcsh, ksh, pdksh and zsh? */
+ static NO_COPY const char *def_shells[] = {
+ "/bin/sh",
+ "/bin/csh",
+ "/usr/bin/sh",
+ "/usr/bin/csh",
+ NULL
+ };
+ static char buf[MAX_PATH];
+ int ch, buf_idx;
+
+ if (!shell_fp && !(shell_fp = fopen (ETC_SHELLS, "rt")))
+ {
+ if (def_shells[shell_index])
+ return strcpy (buf, def_shells[shell_index++]);
+ return NULL;
+ }
+ /* Skip white space characters. */
+ while ((ch = getc (shell_fp)) != EOF && isspace (ch))
+ ;
+ /* Get each non-whitespace character as part of the shell path as long as
+ it fits in buf. */
+ for (buf_idx = 0;
+ ch != EOF && !isspace (ch) && buf_idx < MAX_PATH;
+ buf_idx++, ch = getc (shell_fp))
+ buf[buf_idx] = ch;
+ /* Skip any trailing non-whitespace character not fitting in buf. If the
+ path is longer than MAX_PATH, it's invalid anyway. */
+ while (ch != EOF && !isspace (ch))
+ ch = getc (shell_fp);
+ if (buf_idx)
+ {
+ buf[buf_idx] = '\0';
+ return buf;
+ }
+ return NULL;
+}
+
+extern "C" void
+setusershell ()
+{
+ if (shell_fp)
+ fseek (shell_fp, 0L, SEEK_SET);
+ shell_index = 0;
+}
+
+extern "C" void
+endusershell ()
+{
+ if (shell_fp)
+ fclose (shell_fp);
+ shell_index = 0;
+}
diff --git a/winsup/cygwin/sysconf.cc b/winsup/cygwin/sysconf.cc
index 4c253a1c2e3..b5a2b383de1 100644
--- a/winsup/cygwin/sysconf.cc
+++ b/winsup/cygwin/sysconf.cc
@@ -69,7 +69,6 @@ sysconf (int in)
return 1;
/*FALLTHRU*/
case _SC_PHYS_PAGES:
- case _SC_AVPHYS_PAGES:
if (wincap.supports_smp ())
{
NTSTATUS ret;
@@ -100,11 +99,27 @@ sysconf (int in)
}
case _SC_PHYS_PAGES:
return sbi.NumberOfPhysicalPages;
- case _SC_AVPHYS_PAGES:
- return sbi.HighestPhysicalPage - sbi.LowestPhysicalPage + 1;
}
}
break;
+ case _SC_AVPHYS_PAGES:
+ if (wincap.supports_smp ())
+ {
+ NTSTATUS ret;
+ SYSTEM_PERFORMANCE_INFORMATION spi;
+ if ((ret = NtQuerySystemInformation (SystemPerformanceInformation,
+ (PVOID) &spi,
+ sizeof spi, NULL))
+ != STATUS_SUCCESS)
+ {
+ __seterrno_from_win_error (RtlNtStatusToDosError (ret));
+ debug_printf ("NtQuerySystemInformation: ret = %d, "
+ "Dos(ret) = %d",
+ ret, RtlNtStatusToDosError (ret));
+ return -1;
+ }
+ return spi.AvailablePages;
+ }
}
/* Invalid input or unimplemented sysconf name */
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 516cb8d2b81..937406a8a48 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -1786,12 +1786,11 @@ pthread::thread_init_wrapper (void *_arg)
struct sigaction _sigs[NSIG];
sigset_t _sig_mask; /* one set for everything to ignore. */
- LONG _sigtodo[NSIG + __SIGOFFSET];
// setup signal structures
thread->sigs = _sigs;
thread->sigmask = &_sig_mask;
- thread->sigtodo = _sigtodo;
+ thread->sigtodo = NULL;
memset (&local_winsup, 0, sizeof (struct _winsup_t));
@@ -2784,8 +2783,10 @@ pthread_kill (pthread_t thread, int sig)
if (!pthread::is_good_object (&thread))
return EINVAL;
+#if 0
if (thread->sigs)
myself->setthread2signal (thread);
+#endif
int rval = raise (sig);
@@ -2796,6 +2797,7 @@ pthread_kill (pthread_t thread, int sig)
extern "C" int
pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
{
+#if 0
pthread *thread = pthread::self ();
// lock this myself, for the use of thread2signal
@@ -2803,6 +2805,7 @@ pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
if (thread->sigs)
myself->setthread2signal (thread);
+#endif
int rval = sigprocmask (operation, set, old_set);
diff --git a/winsup/cygwin/times.cc b/winsup/cygwin/times.cc
index 86e9f634356..2def51f45b2 100644
--- a/winsup/cygwin/times.cc
+++ b/winsup/cygwin/times.cc
@@ -142,11 +142,13 @@ totimeval (struct timeval *dst, FILETIME *src, int sub, int flag)
dst->tv_sec = x / (long long) (1e6);
}
+hires_ms gtod;
+UINT NO_COPY hires_ms::minperiod;
+
/* FIXME: Make thread safe */
extern "C" int
gettimeofday (struct timeval *tv, struct timezone *tz)
{
- static hires_ms gtod;
static bool tzflag;
LONGLONG now = gtod.usecs (false);
if (now == (LONGLONG) -1)
@@ -620,45 +622,45 @@ hires_us::usecs (bool justdelta)
return justdelta ? now.QuadPart : primed_ft.QuadPart + now.QuadPart;
}
-void
+UINT
hires_ms::prime ()
{
TIMECAPS tc;
FILETIME f;
- int priority = GetThreadPriority (GetCurrentThread ());
- SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
- if (timeGetDevCaps (&tc, sizeof (tc)) != TIMERR_NOERROR)
- minperiod = 0;
- else
- {
- minperiod = min (max (tc.wPeriodMin, 1), tc.wPeriodMax);
- timeBeginPeriod (minperiod);
- }
+ if (!minperiod)
+ if (timeGetDevCaps (&tc, sizeof (tc)) != TIMERR_NOERROR)
+ minperiod = 1;
+ else
+ {
+ minperiod = min (max (tc.wPeriodMin, 1), tc.wPeriodMax);
+ timeBeginPeriod (minperiod);
+ }
- initime_ms = timeGetTime ();
- GetSystemTimeAsFileTime (&f);
- SetThreadPriority (GetCurrentThread (), priority);
+ if (!inited)
+ {
+ int priority = GetThreadPriority (GetCurrentThread ());
+ SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
+ initime_ms = timeGetTime ();
+ GetSystemTimeAsFileTime (&f);
+ SetThreadPriority (GetCurrentThread (), priority);
- inited = 1;
- initime_us.HighPart = f.dwHighDateTime;
- initime_us.LowPart = f.dwLowDateTime;
- initime_us.QuadPart -= FACTOR;
- initime_us.QuadPart /= 10;
+ inited = 1;
+ initime_us.HighPart = f.dwHighDateTime;
+ initime_us.LowPart = f.dwLowDateTime;
+ initime_us.QuadPart -= FACTOR;
+ initime_us.QuadPart /= 10;
+ }
+ return minperiod;
}
LONGLONG
hires_ms::usecs (bool justdelta)
{
- if (!inited)
+ if (!minperiod) /* NO_COPY variable */
prime ();
DWORD now = timeGetTime ();
// FIXME: Not sure how this will handle the 49.71 day wrap around
LONGLONG res = initime_us.QuadPart + ((LONGLONG) (now - initime_ms) * 1000);
return res;
}
-
-hires_ms::~hires_ms ()
-{
- timeEndPeriod (minperiod);
-}
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index 120ffb5de40..943e9b4f8e9 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -40,6 +40,13 @@ unlockpt (int fd)
}
extern "C" int
+revoke (char *ttyname)
+{
+ set_errno (ENOSYS);
+ return -1;
+}
+
+extern "C" int
ttyslot (void)
{
if (NOTSTATE (myself, PID_USETTY))