|
|
/*++
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; }
|