* environ.cc: Eliminate oldstack CYGWIN option.

* exceptions.cc (sfta): Eliminate obsolete function.
(sgmb): Eliminate obsolete function.
(class stack_info): Remove MS method for walking the stack.
(stack_info::init): Just initialize required fields.
(stack_info::brute_force): Rename to stack_info::walk.
(handle_exceptions): Pass derived frame pointer to sig_send.
(interrupt_setup): Clear saved frame pointer here.
(interrupt_on_return): thestack is no longer a pointer.
(call_handler): Accept a flag to indicate when a signal was sent from other
than the main thread.  Use saved frame pointer for determining where to place
signal handler call.
(sig_handle): Accept "nonmain" argument.  Pass it to call_handler.
* fhandler_tty.cc (fhandler_tty_common::__acquire_output_mutex): Change
debugging output slightly.
* (fhandler_tty_common::__release_output_mutex): Ditto.
(fhandler_tty_slave::read): Fix a comment, remove a goto.
* sigproc.cc (sig_send): Accept an optional frame pointer argument for use when
suspending the main process.  sigcomplete_main is an autoreset event now.  Save
frame pointer for non-main operation.
(wait_sig): Make sigcomplete_main an autoreset event.  Eliminate NOSIGQUEUE.
Pass rc to sig_handle to signify if this was a nonmain process.
* sigproc.h: Reflect change to sig_send argument.
* syscalls.cc (swab): Eliminate swab function since it is now available in
newlib.
* winsup.h (signal_dispatch): Change CONTEXT cx to DWORD ebp.
This commit is contained in:
Christopher Faylor 2000-03-09 21:04:05 +00:00
parent 3072163c0f
commit af1dc7ccea
8 changed files with 132 additions and 181 deletions

View File

@ -1,3 +1,33 @@
Thu Mar 9 15:25:01 2000 Christopher Faylor <cgf@cygnus.com>
* environ.cc: Eliminate oldstack CYGWIN option.
* exceptions.cc (sfta): Eliminate obsolete function.
(sgmb): Eliminate obsolete function.
(class stack_info): Remove MS method for walking the stack.
(stack_info::init): Just initialize required fields.
(stack_info::brute_force): Rename to stack_info::walk.
(handle_exceptions): Pass derived frame pointer to sig_send.
(interrupt_setup): Clear saved frame pointer here.
(interrupt_on_return): thestack is no longer a pointer.
(call_handler): Accept a flag to indicate when a signal was sent from
other than the main thread. Use saved frame pointer for determining
where to place signal handler call.
(sig_handle): Accept "nonmain" argument. Pass it to call_handler.
* fhandler_tty.cc (fhandler_tty_common::__acquire_output_mutex): Change
debugging output slightly.
* (fhandler_tty_common::__release_output_mutex): Ditto.
(fhandler_tty_slave::read): Fix a comment, remove a goto.
* sigproc.cc (sig_send): Accept an optional frame pointer argument for
use when suspending the main process. sigcomplete_main is an autoreset
event now. Save frame pointer for non-main operation.
(wait_sig): Make sigcomplete_main an autoreset event. Eliminate
NOSIGQUEUE. Pass rc to sig_handle to signify if this was a nonmain
process.
* sigproc.h: Reflect change to sig_send argument.
* syscalls.cc (swab): Eliminate swab function since it is now available
in newlib.
* winsup.h (signal_dispatch): Change CONTEXT cx to DWORD ebp.
Tue Mar 7 13:31:10 2000 Christopher Faylor <cgf@cygnus.com>
* sigproc.cc (sig_send): Eliminate sync_sig_send synchronization since

View File

@ -19,7 +19,6 @@ extern BOOL allow_glob;
extern BOOL allow_ntea;
extern BOOL strip_title_path;
extern DWORD chunksize;
extern BOOL oldstack;
BOOL threadsafe;
BOOL reset_com = TRUE;
static BOOL envcache = TRUE;
@ -320,7 +319,6 @@ struct parse_thing
{"glob", {&allow_glob}, justset, NULL, {{FALSE}, {TRUE}}},
{"ntea", {&allow_ntea}, justset, NULL, {{FALSE}, {TRUE}}},
{"ntsec", {&allow_ntsec}, justset, NULL, {{FALSE}, {TRUE}}},
{"oldstack", {&oldstack}, justset, NULL, {{FALSE}, {TRUE}}},
{"reset_com", {&reset_com}, justset, NULL, {{FALSE}, {TRUE}}},
{"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
{"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}},

View File

@ -191,27 +191,11 @@ exception (EXCEPTION_RECORD *e, CONTEXT *in)
#endif
}
extern "C" {
static LPVOID __stdcall
sfta(HANDLE, DWORD)
{
return NULL;
}
static DWORD __stdcall
sgmb(HANDLE, DWORD)
{
return 4;
}
#ifdef __i386__
/* Print a stack backtrace. */
#define HAVE_STACK_TRACE
/* Set from CYGWIN environment variable if want to use old method. */
BOOL NO_COPY oldstack = 0;
/* The function used to load the imagehlp DLL. Returns TRUE if the
DLL was found. */
static LoadDLLinitfunc (imagehlp)
@ -227,53 +211,38 @@ LoadDLLfunc (StackWalk, StackWalk@36, imagehlp)
class stack_info
{
int first_time; /* True if just starting to iterate. */
HANDLE hproc; /* Handle of process to inspect. */
HANDLE hthread; /* Handle of thread to inspect. */
int (stack_info::*get) (HANDLE, HANDLE); /* Gets the next stack frame */
int walk (); /* Uses the "old" method */
public:
STACKFRAME sf; /* For storing the stack information */
int walk (HANDLE, HANDLE); /* Uses the StackWalk function */
int brute_force (HANDLE, HANDLE); /* Uses the "old" method */
void init (CONTEXT *); /* Called the first time that stack info is needed */
void init (DWORD); /* Called the first time that stack info is needed */
stack_info (): first_time(1) {}
/* The constructor remembers hproc and hthread and determines which stack walking
method to use */
stack_info (int use_old_stack, HANDLE hp, HANDLE ht): hproc(hp), hthread(ht)
{
if (!use_old_stack && LoadDLLinitnow (imagehlp))
get = &stack_info::walk;
else
get = &stack_info::brute_force;
}
/* Postfix ++ iterates over the stack, returning zero when nothing is left. */
int operator ++(int) { return (this->*get) (hproc, hthread); }
int operator ++(int) { return this->walk (); }
};
/* The number of parameters used in STACKFRAME */
#define NPARAMS (sizeof(thestack->sf.Params) / sizeof(thestack->sf.Params[0]))
#define NPARAMS (sizeof(thestack.sf.Params) / sizeof(thestack.sf.Params[0]))
/* This is the main stack frame info for this process. */
static stack_info *thestack = NULL;
static signal_dispatch sigsave;
static NO_COPY stack_info thestack;
signal_dispatch NO_COPY sigsave;
/* Initialize everything needed to start iterating. */
void
stack_info::init (CONTEXT *cx)
stack_info::init (DWORD ebp)
{
first_time = 1;
memset (&sf, 0, sizeof(sf));
sf.AddrPC.Offset = cx->Eip;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrStack.Offset = cx->Esp;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrFrame.Offset = cx->Ebp;
sf.AddrFrame.Offset = ebp;
sf.AddrPC.Offset = ((DWORD *) ebp)[1];
sf.AddrFrame.Mode = AddrModeFlat;
}
/* Walk the stack by looking at successive stored 'bp' frames.
This is not foolproof. */
int
stack_info::brute_force (HANDLE, HANDLE)
stack_info::walk ()
{
char **ebp;
if (first_time)
@ -300,44 +269,20 @@ stack_info::brute_force (HANDLE, HANDLE)
return 1;
}
/* Use Win32 StackWalk() API to display the stack. This is theoretically
more foolproof than the brute force method above. */
int
stack_info::walk (HANDLE hproc, HANDLE hthread)
{
#ifdef SOMEDAY
/* It would be nice to get more information (like DLL symbols and module name)
for each stack frame but in order to do that we have to call SymInitialize.
It doesn't seem to be possible to do this inside of an excaption handler for
some reason. */
static int initialized = 0;
if (!initialized && !SymInitialize(hproc, NULL, TRUE))
small_printf("SymInitialize error, %E\n");
initialized = 1;
#endif
return StackWalk (IMAGE_FILE_MACHINE_I386, hproc, hthread, &sf, NULL, NULL,
sfta, sgmb, NULL) && !!sf.AddrFrame.Offset;
}
/* Dump the stack using either the old method or the new Win32 API method */
void
stack (HANDLE hproc, HANDLE hthread, CONTEXT *cx)
{
int i;
/* Set this up if it's the first time. */
if (!thestack)
thestack = new stack_info (oldstack, hproc, hthread);
thestack->init (cx); /* Initialize from the input CONTEXT */
thestack.init (cx->Ebp); /* Initialize from the input CONTEXT */
small_printf ("Stack trace:\r\nFrame Function Args\r\n");
for (i = 0; i < 16 && (*thestack)++ ; i++)
for (i = 0; i < 16 && thestack++ ; i++)
{
small_printf ("%08x %08x ", thestack->sf.AddrFrame.Offset,
thestack->sf.AddrPC.Offset);
small_printf ("%08x %08x ", thestack.sf.AddrFrame.Offset,
thestack.sf.AddrPC.Offset);
for (unsigned j = 0; j < NPARAMS; j++)
small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack->sf.Params[j]);
small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack.sf.Params[j]);
small_printf (")\r\n");
}
small_printf ("End of stack trace%s",
@ -551,18 +496,15 @@ handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
debug_printf ("In cygwin_except_handler calling %p",
myself->getsig(sig).sa_handler);
DWORD *bp = (DWORD *)in->Esp;
for (DWORD *bpend = bp - 8; bp > bpend; bp--)
if (*bp == in->SegCs && bp[-1] == in->Eip)
DWORD *ebp = (DWORD *)in->Esp;
for (DWORD *bpend = ebp - 8; ebp > bpend; ebp--)
if (*ebp == in->SegCs && ebp[-1] == in->Eip)
{
bp -= 2;
ebp -= 2;
break;
}
in->Ebp = (DWORD) bp;
sigsave.cx = in;
sig_send (NULL, sig); // Signal myself
sigsave.cx = NULL;
sig_send (NULL, sig, (DWORD) ebp); // Signal myself
return 0;
}
#endif /* __i386__ */
@ -574,7 +516,6 @@ stack (void)
system_printf ("Stack trace not yet supported on this machine.");
}
#endif
}
/* Utilities to call a user supplied exception handler. */
@ -659,6 +600,7 @@ interrupt_setup (int sig, struct sigaction& siga, void *handler, DWORD retaddr)
sigsave.func = (void (*)(int)) handler;
sigsave.sig = sig;
sigsave.saved_errno = -1; // Flag: no errno to save
sigsave.ebp = 0;
}
static void
@ -670,24 +612,19 @@ interrupt_now (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
}
static int
interrupt_on_return (CONTEXT *ctx, int sig, struct sigaction& siga, void *handler)
interrupt_on_return (DWORD ebp, int sig, struct sigaction& siga, void *handler)
{
int i;
if (sigsave.sig)
return 0; /* Already have a signal stacked up */
/* Set this up if it's the first time. */
/* FIXME: Eventually augment to handle more than one thread */
if (!thestack)
thestack = new stack_info (oldstack, hMainProc, hMainThread);
thestack->init (ctx); /* Initialize from the input CONTEXT */
for (i = 0; i < 32 && (*thestack)++ ; i++)
if (interruptible (thestack->sf.AddrReturn.Offset))
thestack.init (ebp); /* Initialize from the input CONTEXT */
for (i = 0; i < 32 && thestack++ ; i++)
if (interruptible (thestack.sf.AddrReturn.Offset))
{
DWORD *addr_retaddr = ((DWORD *)thestack->sf.AddrFrame.Offset) + 1;
if (*addr_retaddr == thestack->sf.AddrReturn.Offset)
DWORD *addr_retaddr = ((DWORD *)thestack.sf.AddrFrame.Offset) + 1;
if (*addr_retaddr == thestack.sf.AddrReturn.Offset)
{
interrupt_setup (sig, siga, handler, *addr_retaddr);
*addr_retaddr = (DWORD) sigdelayed;
@ -707,11 +644,12 @@ set_sig_errno (int e)
}
static int
call_handler (int sig, struct sigaction& siga, void *handler)
call_handler (int sig, struct sigaction& siga, void *handler, int nonmain)
{
CONTEXT *cx, orig;
CONTEXT cx;
DWORD ebp;
int interrupted = 1;
HANDLE hth;
HANDLE hth = NULL;
int res;
if (hExeced != NULL && hExeced != INVALID_HANDLE_VALUE)
@ -721,56 +659,52 @@ call_handler (int sig, struct sigaction& siga, void *handler)
exec_exit = sig; // Maybe we'll exit with this value
goto out1;
}
hth = myself->getthread2signal ();
/* Suspend the thread which will receive the signal. But first ensure that
this thread doesn't have the sync_proc_subproc and mask_sync mutos, since
we need those (hack alert). If the thread-to-be-suspended has either of
these mutos, enter a busy loop until it is released. If the thread is
already suspended (which should never occur) then just queue the signal. */
for (;;)
{
sigproc_printf ("suspending mainthread");
res = SuspendThread (hth);
/* FIXME: Make multi-thread aware */
for (muto *m = muto_start.next; m != NULL; m = m->next)
if (m->unstable () || m->owner () == maintid)
goto keep_looping;
break;
keep_looping:
sigproc_printf ("suspended thread owns a muto");
if (res)
goto set_pending;
ResumeThread (hth);
Sleep (0);
}
sigproc_printf ("SuspendThread returned %d", res);
if (sigsave.cx)
{
cx = sigsave.cx;
sigsave.cx = NULL;
}
if (!nonmain)
ebp = sigsave.ebp;
else
{
cx = &orig;
/* FIXME - this does not preserve FPU state */
orig.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, cx))
hth = myself->getthread2signal ();
/* Suspend the thread which will receive the signal. But first ensure that
this thread doesn't have the sync_proc_subproc and mask_sync mutos, since
we need those (hack alert). If the thread-to-be-suspended has either of
these mutos, enter a busy loop until it is released. If the thread is
already suspended (which should never occur) then just queue the signal. */
for (;;)
{
sigproc_printf ("suspending mainthread");
res = SuspendThread (hth);
/* FIXME: Make multi-thread aware */
for (muto *m = muto_start.next; m != NULL; m = m->next)
if (m->unstable () || m->owner () == maintid)
goto keep_looping;
break;
keep_looping:
sigproc_printf ("suspended thread owns a muto");
if (res)
goto set_pending;
ResumeThread (hth);
Sleep (0);
}
sigproc_printf ("SuspendThread returned %d", res);
cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext (hth, &cx))
{
system_printf ("couldn't get context of main thread, %E");
goto out;
}
ebp = cx.Ebp;
}
if (cx == &orig && interruptible (cx->Eip))
interrupt_now (cx, sig, siga, handler);
else if (!interrupt_on_return (cx, sig, siga, handler))
if (nonmain && interruptible (cx.Eip))
interrupt_now (&cx, sig, siga, handler);
else if (!interrupt_on_return (ebp, sig, siga, handler))
{
set_pending:
pending_signals = 1; /* FIXME: Probably need to be more tricky here */
@ -780,15 +714,20 @@ call_handler (int sig, struct sigaction& siga, void *handler)
if (interrupted)
{
(void) SetEvent (signal_arrived); // For an EINTR case
res = SetEvent (signal_arrived); // For an EINTR case
sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
/* Clear any waiting threads prior to dispatching to handler function */
proc_subproc(PROC_CLEARWAIT, 1);
}
out:
res = ResumeThread (hth);
sigproc_printf ("ResumeThread returned %d", res);
if (!hth)
sigproc_printf ("modified main-thread stack");
else
{
res = ResumeThread (hth);
sigproc_printf ("ResumeThread returned %d", res);
}
out1:
sigproc_printf ("returning %d", interrupted);
@ -892,7 +831,7 @@ sig_handle_tty_stop (int sig)
}
int __stdcall
sig_handle (int sig)
sig_handle (int sig, int nonmain)
{
int rc = 0;
@ -971,7 +910,7 @@ stop:
dosig:
/* Dispatch to the appropriate function. */
sigproc_printf ("signal %d, about to call %p", sig, thissig.sa_handler);
rc = call_handler (sig, thissig, handler);
rc = call_handler (sig, thissig, handler, nonmain);
done:
sigproc_printf ("returning %d", rc);

View File

@ -110,7 +110,10 @@ fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln,
DWORD res = WaitForSingleObject (output_mutex, ms);
if (res == WAIT_OBJECT_0)
{
#ifdef DEBUGGING
#ifndef DEBUGGING
if (strace.active)
strace.prntf (_STRACE_TERMIOS, "%F (%d): tty output_mutex: acquired", fn, ln, res);
#else
ostack[osi].fn = fn;
ostack[osi].ln = ln;
ostack[osi].tname = threadname (0, 0);
@ -118,8 +121,6 @@ fhandler_tty_common::__acquire_output_mutex (const char *fn, int ln,
osi++;
#endif
}
if (strace.active)
strace.prntf (_STRACE_TERMIOS, "%F (%d): tty output_mutex: acquired", fn, ln, res);
return res;
}
@ -128,7 +129,10 @@ fhandler_tty_common::__release_output_mutex (const char *fn, int ln)
{
if (ReleaseMutex (output_mutex))
{
#ifdef DEBUGGING
#ifndef DEBUGGING
if (strace.active)
strace.prntf (_STRACE_TERMIOS, "%F (%d): tty output_mutex released", fn, ln);
#else
if (osi > 0)
osi--;
termios_printf ("released at %s:%d, osi %d", fn, ln, osi);
@ -136,8 +140,6 @@ fhandler_tty_common::__release_output_mutex (const char *fn, int ln)
ostack[osi].ln = -ln;
#endif
}
if (strace.active)
strace.prntf (_STRACE_TERMIOS, "%F (%d): tty output_mutex released", fn, ln);
}
#define acquire_output_mutex(ms) \
@ -288,7 +290,10 @@ again:
}
if (get_ttyp ()->OutputStopped)
WaitForSingleObject (restart_output_event, INFINITE);
{
termios_printf ("waiting for restart_output_event");
WaitForSingleObject (restart_output_event, INFINITE);
}
if (get_ttyp ()->ti.c_oflag & OPOST) // post-process output
{
@ -575,7 +580,6 @@ fhandler_tty_slave::read (void *ptr, size_t len)
while (len)
{
wait:
termios_printf ("reading %d bytes (vtime %d)",
min ((unsigned) vmin, min (len, sizeof (buf))), vtime);
if (ReadFile (get_handle (), (unsigned *) buf,
@ -614,7 +618,7 @@ fhandler_tty_slave::read (void *ptr, size_t len)
if (get_flags () & (O_NONBLOCK | O_NDELAY))
break;
/* We can't enter to blocking Readfile - signals will be lost!
/* We can't enter the blocking Readfile as signals will be lost.
* So, poll the pipe for data.
* FIXME: try to avoid polling...
* FIXME: Current EINTR scheme does not take vmin/vtime into account.
@ -625,7 +629,7 @@ fhandler_tty_slave::read (void *ptr, size_t len)
if (vmin == 0 && vtime == 0)
return 0; // min = 0, time = 0
if (vtime == 0)
goto wait; // min > 0, time = 0
continue; // min > 0, time = 0
while (vtime--)
{
PeekNamedPipe (get_handle (), NULL, 0, NULL, &n, NULL);

View File

@ -708,7 +708,7 @@ sigproc_terminate (void)
* completed before returning.
*/
int __stdcall
sig_send (pinfo *p, int sig)
sig_send (pinfo *p, int sig, DWORD ebp)
{
int rc = 1;
DWORD tid = GetCurrentThreadId ();
@ -716,6 +716,7 @@ sig_send (pinfo *p, int sig)
HANDLE thiscatch = NULL;
HANDLE thiscomplete = NULL;
BOOL wait_for_completion;
extern signal_dispatch sigsave;
if (p == myself_nowait_nonmain)
p = (tid == maintid) ? myself : myself_nowait;
@ -756,7 +757,7 @@ sig_send (pinfo *p, int sig)
{
thiscatch = sigcatch_main;
thiscomplete = sigcomplete_main;
ResetEvent (thiscomplete);
sigsave.ebp = ebp ?: (DWORD) __builtin_frame_address (1);
}
}
else if (!(thiscatch = getsem (p, "sigcatch", 0, 0)))
@ -1158,7 +1159,7 @@ wait_sig (VOID *)
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 = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
sigcomplete_main = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
sigproc_printf ("sigcatch_nonmain %p", sigcatch_nonmain);
/* Setting dwProcessId flags that this process is now capable of receiving
@ -1231,11 +1232,7 @@ wait_sig (VOID *)
int dispatched_sigchld = 0;
for (int sig = -__SIGOFFSET; sig < NSIG; sig++)
{
#ifdef NOSIGQUEUE
if (InterlockedExchange (myself->getsigtodo(sig), 0L) > 0)
#else
while (InterlockedDecrement (myself->getsigtodo(sig)) >= 0)
#endif
{
if (sig == SIGCHLD)
saw_sigchld = 1;
@ -1263,7 +1260,7 @@ wait_sig (VOID *)
/* Signalled from a child process that it has stopped */
case __SIGCHILDSTOPPED:
sip_printf ("Received child stopped notification");
dispatched |= sig_handle (SIGCHLD);
dispatched |= sig_handle (SIGCHLD, rc);
if (proc_subproc (PROC_CHILDSTOPPED, 0))
dispatched |= 1;
break;
@ -1271,18 +1268,16 @@ wait_sig (VOID *)
/* A normal UNIX signal */
default:
sip_printf ("Got signal %d", sig);
int wasdispatched = sig_handle (sig);
int wasdispatched = sig_handle (sig, rc);
dispatched |= wasdispatched;
if (sig == SIGCHLD && wasdispatched)
dispatched_sigchld = 1;
goto nextsig;
}
}
#ifndef NOSIGQUEUE
/* Decremented too far. */
if (InterlockedIncrement (myself->getsigtodo(sig)) > 0)
pending_signals = 1;
#endif
nextsig:
continue;
}

View File

@ -37,7 +37,7 @@ extern HANDLE signal_arrived;
BOOL __stdcall my_parent_is_alive ();
extern "C" int __stdcall sig_dispatch_pending (int force = FALSE) __asm__ ("sig_dispatch_pending");
extern "C" void __stdcall set_process_mask (sigset_t newmask);
int __stdcall sig_handle (int);
int __stdcall sig_handle (int, int);
void __stdcall sig_clear (int);
void __stdcall sig_set_pending (int);
int __stdcall handle_sigsuspend (sigset_t);
@ -48,7 +48,7 @@ void __stdcall subproc_init ();
void __stdcall sigproc_terminate ();
BOOL __stdcall proc_exists (pinfo *);
int __stdcall proc_subproc (DWORD, DWORD);
int __stdcall sig_send (pinfo *, int);
int __stdcall sig_send (pinfo *, int, DWORD ebp = 0);
extern char myself_nowait_dummy[];
extern char myself_nowait_nonmain_dummy[];

View File

@ -1841,21 +1841,6 @@ ffs (int i)
return table[x >> a] + a;
}
extern "C"
void
swab (const void *src, void *dst, ssize_t n)
{
const char *from = (const char *) src;
char *to = (char *) dst;
while (n > 1)
{
const char b0 = from[--n], b1 = from[--n];
to[n] = b0;
to[n + 1] = b1;
}
}
extern "C"
void
login (struct utmp *ut)

View File

@ -307,7 +307,7 @@ struct signal_dispatch
void (*func) (int);
int sig;
int saved_errno;
CONTEXT *cx;
DWORD ebp;
DWORD oldmask;
DWORD retaddr;
};