NT4/private/posix/psxss/sigapi.c

430 lines
8.3 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
sigapi.c
Abstract:
This module implements all signal oriented APIs.
Author:
Mark Lucovsky (markl) 30-Mar-1989
Revision History:
--*/
#include "psxsrv.h"
BOOLEAN
PsxSigAction (
IN PPSX_PROCESS p,
IN OUT PPSX_API_MSG m
)
/*++
Routine Description:
This procedure implements POSIX sigaction
Arguments:
p - Supplies the address of the process making the call.
m - Supplies the address of the message associated with the open request.
Return Value:
TRUE - The contens of *m should be used to generate a reply.
--*/
{
PPSX_SIGACTION_MSG args;
args = &m->u.SigAction;
//
// Validate Signal
//
if ( !ISSIGNOINRANGE(args->Sig) || args->Sig <= 0 ) {
m->Error = EINVAL;
return TRUE;
}
if (ARGUMENT_PRESENT(args->ActSpecified) ) {
//
// Since call is attempting to set a signal action, fail if:
// attemping to catch a signal that cant be caught
// SIGKILL, SIGSTOP
// attemping to ignore a signal that cant be ignored
// SIGKILL, SIGSTOP
//
// SIGKILL and SIGSTOP can only be set to SIG_DFL !
//
if ( ((args->Sig == SIGKILL) || (args->Sig == SIGSTOP)) &&
(args->Act.sa_handler != (_handler) SIG_DFL) ) {
m->Error = EINVAL;
return TRUE;
} else {
//
// Clear SIGKILL and SIGSTOP from the new block
// mask without causing an error
//
SIGDELSET(&args->Act.sa_mask, SIGKILL);
SIGDELSET(&args->Act.sa_mask, SIGSTOP);
args->Act.sa_mask &= _SIGFULLSET;
AcquireProcessLock(p);
args->Oact = p->SignalDataBase.SignalDisposition[args->Sig-1];
p->SignalDataBase.SignalDisposition[args->Sig-1] = args->Act;
if (SIGISMEMBER(&p->SignalDataBase.PendingSignalMask, args->Sig) ) {
//
// Signal whose action is being changed is pending.
//
// If signal iction is being set to ignored, or if being set to
// default action, and default action is to ignore the signal,
// then clear the signal from the set of pending signals.
//
if ( (args->Act.sa_handler == SIG_IGN) ||
((args->Act.sa_handler == SIG_DFL) && (args->Sig == SIGCHLD)) ) {
SIGDELSET(&p->SignalDataBase.PendingSignalMask, args->Sig);
}
}
ReleaseProcessLock(p);
}
} else {
AcquireProcessLock(p);
args->Oact = p->SignalDataBase.SignalDisposition[args->Sig-1];
ReleaseProcessLock(p);
}
return TRUE;
}
BOOLEAN
PsxSigProcMask(
IN PPSX_PROCESS p,
IN PPSX_API_MSG m
)
/*++
Routine Description:
This procedure implements POSIX sigaction
Arguments:
p - Supplies the address of the process making the call.
m - Supplies the address of the message associated with the open request.
Return Value:
TRUE - The contens of *m should be used to generate a reply.
--*/
{
PPSX_SIGPROCMASK_MSG args;
args = &m->u.SigProcMask;
AcquireProcessLock(p);
args->Oset = p->SignalDataBase.BlockedSignalMask;
if ( ARGUMENT_PRESENT(args->SetSpecified) ) {
switch (args->How) {
case SIG_BLOCK:
p->SignalDataBase.BlockedSignalMask |= args->Set;
break;
case SIG_UNBLOCK:
p->SignalDataBase.BlockedSignalMask &= ~args->Set;
break;
case SIG_SETMASK:
p->SignalDataBase.BlockedSignalMask = args->Set;
break;
default:
m->Error = EINVAL;
ReleaseProcessLock(p);
return TRUE;
}
SIGDELSET(&p->SignalDataBase.BlockedSignalMask,SIGKILL);
SIGDELSET(&p->SignalDataBase.BlockedSignalMask,SIGSTOP);
}
ReleaseProcessLock(p);
return TRUE;
}
BOOLEAN
PsxSigPending(
IN PPSX_PROCESS p,
IN PPSX_API_MSG m
)
{
PPSX_SIGPENDING_MSG args;
args = &m->u.SigPending;
args->Set = p->SignalDataBase.PendingSignalMask;
m->Error = 0;
return TRUE;
}
BOOLEAN
PsxSigSuspend(
IN PPSX_PROCESS p,
IN PPSX_API_MSG m
)
/*++
Routine Description:
This procedure implements POSIX sigsuspend
Arguments:
p - Supplies the address of the process making the call.
m - Supplies the address of the message associated with the request.
Return Value:
FALSE - A reply will not be generated until a signal is generated that
either terminates the process or is delivered to the process.
--*/
{
PPSX_SIGSUSPEND_MSG args;
sigset_t NewBlockMask;
NTSTATUS Status;
args = &m->u.SigSuspend;
AcquireProcessLock(p);
NewBlockMask = p->SignalDataBase.BlockedSignalMask;
//
// For sigsuspend, sigmask is specified; otherwise, the current
// blocked signal mask is used
//
if ( args->SigMaskSpecified ) {
p->SignalDataBase.BlockedSignalMask = args->SigMask;
}
SIGDELSET(&p->SignalDataBase.BlockedSignalMask,SIGKILL);
SIGDELSET(&p->SignalDataBase.BlockedSignalMask,SIGSTOP);
ReleaseProcessLock(p);
Status = BlockProcess(p, (PVOID)NewBlockMask, PsxSigSuspendHandler,
m, FALSE, NULL);
if (!NT_SUCCESS(Status)) {
m->Error = PsxStatusToErrno(Status);
return TRUE;
}
//
// The process was blocked -- don't reply to the api request yet.
//
return FALSE;
}
BOOLEAN
PsxNull (
IN PPSX_PROCESS p,
IN OUT PPSX_API_MSG m
)
/*++
Routine Description:
The null system service. This service is used to get a process to
look at its pending signals.
Arguments:
p - Supplies the address of the process making the call.
m - Supplies the address of the message associated with the request.
Return Value:
TRUE - The contens of *m should be used to generate a reply.
--*/
{
//
// The process may fork again.
//
p->Flags &= ~P_NO_FORK;
return TRUE;
}
BOOLEAN
PsxKill(
IN PPSX_PROCESS p,
IN PPSX_API_MSG m
)
/*++
Routine Description:
This function implements posix kill().
Arguments:
p - Supplies the address of the calling process
m - Supplies the address of the related message
Return Value:
TRUE - Always succeeds and generates a reply
--*/
{
PPSX_KILL_MSG args;
PPSX_PROCESS cp;
BOOLEAN SignalSent;
pid_t TargetGroup;
args = &m->u.Kill;
if ( ! ISSIGNOINRANGE(args->Sig) ) {
m->Error = EINVAL;
return TRUE;
}
if ( args->Pid < 0 && args->Pid != -1 ) {
TargetGroup = args->Pid * -1;
} else {
TargetGroup = 0;
}
SignalSent = FALSE;
//
// Lock the process table so that we can scan process table.
//
AcquireProcessStructureLock();
//
// Scan process table looking for pid
//
for (cp = FirstProcess; cp < LastProcess; cp++) {
//
// Only look at non-free slots
//
if (cp->Flags & P_FREE) {
continue;
}
if (args->Pid > 0) {
//
// Send signal to process whose Pid is args->Pid
//
if (cp->Pid == args->Pid) {
PsxSignalProcess(cp, args->Sig);
SignalSent = TRUE;
}
}
if (args->Pid == 0) {
//
// Send signal to all processes whose process group id
// matches the caller
//
if (cp->ProcessGroupId == p->ProcessGroupId) {
PsxSignalProcess(cp, args->Sig);
SignalSent = TRUE;
}
}
if (args->Pid == -1) {
//
// Posix does not define this.
//
continue;
}
if (TargetGroup) {
//
// Send signal to all processes whose process group id
// matches the absolute value of args->Pid
//
if ( cp->ProcessGroupId == TargetGroup ) {
PsxSignalProcess(cp, args->Sig);
SignalSent = TRUE;
}
}
}
if (!SignalSent) {
m->Error = ESRCH;
}
ReleaseProcessStructureLock();
return TRUE;
}