File:  [Atari MiNT] / MiNT / src / dossig.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:59:01 2018 UTC (8 years, 1 month ago) by root
Branches: mint, MAIN
CVS tags: mint112, HEAD
MiNT 1.12

/*

Copyright 1990,1991,1992,1994 Eric R. Smith.

All rights reserved.

*/



/* dossig.c:: dos signal handling routines */



#include "mint.h"



void ARGS_ON_STACK sig_user P_((int vec));



/*

 * send a signal to another process. If pid > 0, send the signal just to

 * that process. If pid < 0, send the signal to all processes whose process

 * group is -pid. If pid == 0, send the signal to all processes with the

 * same process group id.

 *

 * note: post_sig just posts the signal to the process.

 */



long ARGS_ON_STACK

p_kill(pid, sig)

	int pid, sig;

{

	PROC *p;

	long r;



	TRACE(("Pkill(%d, %d)", pid, sig));

	if (sig < 0 || sig >= NSIG) {

		DEBUG(("Pkill: signal out of range"));

		return ERANGE;

	}



	if (pid < 0)

		r = killgroup(-pid, sig, 0);

	else if (pid == 0)

		r = killgroup(curproc->pgrp, sig, 0);

	else {

		p = pid2proc(pid);

		if (p == 0 || p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) {

			DEBUG(("Pkill: pid %d not found", pid));

			return EFILNF;

		}

		if (curproc->euid && curproc->ruid != p->ruid) {

			DEBUG(("Pkill: wrong user"));

			return EACCDN;

		}



/* if the user sends signal 0, don't deliver it -- for users, signal

 * 0 is a null signal used to test the existence of a process

 */

		if (sig != 0)

			post_sig(p, sig);

		r = 0;

	}



	if (r == 0) {

		check_sigs();

		TRACE(("Pkill: returning OK"));

	}

	return r;

}



/*

 * set a user-specified signal handler, POSIX.1 style

 * "oact", if non-null, gets the old signal handling

 * behaviour; "act", if non-null, specifies new

 * behaviour

 */



long ARGS_ON_STACK

p_sigaction(sig, act, oact)

	int sig;

	const struct sigaction *act;

	struct sigaction *oact;

{

	TRACE(("Psigaction(%d)", sig));

	if (sig < 1 || sig >= NSIG)

		return ERANGE;

	if (act && (sig == SIGKILL || sig == SIGSTOP))

		return EACCDN;

	if (oact) {

		oact->sa_handler = curproc->sighandle[sig];

		oact->sa_mask = curproc->sigextra[sig];

		oact->sa_flags = curproc->sigflags[sig] & SAUSER;

	}

	if (act) {

		ushort flags;



		curproc->sighandle[sig] = act->sa_handler;

		curproc->sigextra[sig] = act->sa_mask & ~UNMASKABLE;



/* only the flags in SAUSER can be changed by the user */

		flags = curproc->sigflags[sig] & ~SAUSER;

		flags |= act->sa_flags & SAUSER;

		curproc->sigflags[sig] = flags;

 

/* various special things that should happen */

		if (act->sa_handler == SIG_IGN) {

			/* discard pending signals */

			curproc->sigpending &= ~(1L<<sig);

		}



/* I dunno if this is right, but bash seems to expect it */

 		curproc->sigmask &= ~(1L<<sig);

	}

	return 0;

}



/*

 * set a user-specified signal handler

 */



long ARGS_ON_STACK

p_signal(sig, handler)

	int sig;

	long handler;

{

	long oldhandle;



	TRACE(("Psignal(%d, %lx)", sig, handler));

	if (sig < 1 || sig >= NSIG)

		return ERANGE;

	if (sig == SIGKILL || sig == SIGSTOP)

		return EACCDN;

	oldhandle = curproc->sighandle[sig];

	curproc->sighandle[sig] = handler;

	curproc->sigextra[sig] = 0;

	curproc->sigflags[sig] = 0;



/* various special things that should happen */

	if (handler == SIG_IGN) {

		/* discard pending signals */

		curproc->sigpending &= ~(1L<<sig);

	}



/* I dunno if this is right, but bash seems to expect it */

	curproc->sigmask &= ~(1L<<sig);



	return oldhandle;

}



/*

 * block some signals. Returns the old signal mask.

 */



long ARGS_ON_STACK

p_sigblock(mask)

	ulong mask;

{

	ulong oldmask;



	TRACE(("Psigblock(%lx)",mask));

/* some signals (e.g. SIGKILL) can't be masked */

	mask &= ~(UNMASKABLE);

	oldmask = curproc->sigmask;

	curproc->sigmask |= mask;

	return oldmask;

}



/*

 * set the signals that we're blocking. Some signals (e.g. SIGKILL)

 * can't be masked.

 * Returns the old mask.

 */



long ARGS_ON_STACK

p_sigsetmask(mask)

	ulong mask;

{

	ulong oldmask;



	TRACE(("Psigsetmask(%lx)",mask));

	oldmask = curproc->sigmask;

	curproc->sigmask = mask & ~(UNMASKABLE);

	check_sigs();	/* maybe we unmasked something */

	return oldmask;

}



/*

 * p_sigpending: return which signals are pending delivery

 */



long ARGS_ON_STACK

p_sigpending()

{

	TRACE(("Psigpending()"));

	check_sigs();	/* clear out any that are going to be delivered soon */



/* note that signal #0 is used internally, so we don't tell the process

 * about it

 */

	return curproc->sigpending & ~1L;

}



/*

 * p_sigpause: atomically set the signals that we're blocking, then pause.

 * Some signals (e.g. SIGKILL) can't be masked.

 */



long ARGS_ON_STACK

p_sigpause(mask)

	ulong mask;

{

	ulong oldmask;



	TRACE(("Psigpause(%lx)", mask));

	oldmask = curproc->sigmask;

	curproc->sigmask = mask & ~(UNMASKABLE);

	if (curproc->sigpending & ~(curproc->sigmask))

		check_sigs();	/* a signal is immediately pending */

	else

		sleep(IO_Q, -1L);

	curproc->sigmask = oldmask;

	check_sigs();	/* maybe we unmasked something */

	TRACE(("Psigpause: returning OK"));

	return 0;

}



/*

 * p_sigintr: Set an exception vector to send us the specified signal.

 */



typedef struct usig {

	int vec;		/* exception vector number */

	int sig;		/* signal to send */

	PROC *proc;		/* process to get signal */

	long oldv;		/* old exception vector value */

	struct usig *next;	/* next entry ... */

} usig;



static usig *usiglst;

extern long mcpu;



long ARGS_ON_STACK

p_sigintr(vec, sig)

	int vec;

	int sig;

{

	extern void new_intr();	/* in intr.spp */

	long vec2;

	usig *new;



	if (!sig)		/* ignore signal 0 */

		return 0;



	vec2 = (long) new_intr;



#ifndef ONLY030

	if (mcpu == 0)			

		/* put vector number in high byte of vector address */

		vec2 |= ((long) vec) << 24;

#endif

	new = kmalloc(sizeof(usig));

	if (!new)			/* hope this never happens...! */

		return ENSMEM;

	new->vec = vec;

	new->sig = sig;

	new->proc = curproc;

	new->next = usiglst;		/* simple unsorted list... */

	usiglst = new;



	new->oldv = setexc(vec, vec2);

	return new->oldv;

}



/*

 * Find the process that requested this interrupt, and send it a signal.

 * Called at interrupt time by new_intr() from intr.spp, with interrupt

 * vector number on the stack.

 */



void ARGS_ON_STACK

sig_user(vec)

	int vec;

{

	usig *ptr;



	for (ptr = usiglst; ptr; ptr=ptr->next)

		if (vec == ptr->vec) {

			if (ptr->proc->wait_q != ZOMBIE_Q &&

			    ptr->proc->wait_q != TSR_Q) {

				post_sig(ptr->proc, ptr->sig);

			}

#if 0	/* Search entire list, to allow multiple processes to respond to

	   the same interrupt. (Why/when would you want that?) */

			break;

#endif

		}

	/*

	 * Clear in-service bit for ST MFP interrupts

	 */

	if (vec >= 64 && vec < 80) {

		char *mfp, c;



		if (vec < 72)		/* Register B */

			mfp = (char *)0xfffffa11L;

		else			/* Register A */

			mfp = (char *)0xfffffa0fL;

		c = 1 << (vec & 7);



		*mfp = ~c;

	}

}



/*

 * cancelsigintrs: remove any interrupts requested by this process, called

 * at process termination.

 */

void

cancelsigintrs()

{

	usig *ptr, **old, *nxt;

	short s = spl7();



	for (old=&usiglst, ptr=usiglst; ptr; ) {

		nxt = ptr->next;

		if (ptr->proc == curproc) {

			setexc(ptr->vec, ptr->oldv);

			*old = nxt;

			kfree(ptr);

		} else {

			old = &(ptr->next);

		}

		ptr = nxt;

	}

	spl(s);

}


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.