[net.sources] jobs emulator for 4.2 windows

john@genrad.UUCP (John Nelson) (01/10/84)

The Maryland Windows library source comes with a jobs.c file which emulates
the BSD 4.1 signal mechinism on non-4.1 systems.  I modified this source
file for use with BSD 4.2 as well.  The source file, below, will automatically
detect a 4.2 system, and will provide different code on 4.2 systems vs.
other systems.  This code HAS been tried out, and so far, no one has
complained of problems in the way it functions.

Note that you might have to modify the Makefile line "JOBSOBS" to be

JOBSOBS=jobs.o

if you are converting from a 4.1 system to a 4.2 system.  Also, this jobs
emulator source file might prove useful in converting other programs that
use the 4.1 jobs library.

######## delete this line and all text above for the file "jobs.c" ########

#include <signal.h>

/* Copyright (c) 1983 University of Maryland Computer Science Department */

/*
 * Jobs library emulator using old signal mechanism
 *
 * Added Jobs library emulator for BSD4.2 (genrad!john 01/10/84)
 *
 * 26 March 1983 ACT
 *
 * held_sigs	  == the signals held via sighold()
 * executing_sigs == the signals held because the signal handler is already
 *		     running
 * pending_sigs   == the signals pending, for sigrelse() or whatever
 */

#ifdef SIGVTALRM
#define BSD42
#endif

#ifdef BSD42
typedef int (*FUNCPTR)();

FUNCPTR sigset (signo, f)
register signo;
FUNCPTR f;
{
	FUNCPTR signal();
	return signal(signo, f);
}

FUNCPTR sigignore (signo)
int signo;
{
	return sigset (signo, SIG_IGN);
}

sighold (signo)
int signo;
{
	sigblock (1 << (signo - 1));
}

sigrelse (signo)
int signo;
{
	sigsetmask (sigblock(0) & ~(1 << (signo - 1)));
}



#else not BSD42
static long held_sigs, pending_sigs, executing_sigs;
static int (*sigfuncs[32])();
int sigcatch();

int (*sigset (signo, f))()
register signo;
int (*f)();
{
	int (*rv)() = sigfuncs[signo];

	if (f == SIG_DFL || f == SIG_IGN) {	/* these are just zap-em-ins */
		sigfuncs[signo] = f;
		signal (signo, f);
		pending_sigs &= ~(1<<signo);
		return rv;
	}
	sigfuncs[signo] = f;
	signal (signo, sigcatch);	/* sigcatch() does the real work */
	return rv;
}

int (*sigignore (signo))()
int signo;
{
	sigset (signo, SIG_IGN);
}

/* This is easy too ... */
sighold (signo)
int signo;
{
	held_sigs |= 1 << signo;
}

sigrelse (signo)
int signo;
{
	register sigbit = 1 << signo;

	held_sigs &= ~sigbit;
	if (pending_sigs & sigbit)
		sigcatch (signo);	/* sigcatch() does the real work */
}

/* RACE CONDITIONS ABOUND! */
/* This code assumes that if a second signal occurs it will be during
   the user's function.  That isn't quite true, but... that's the way
   it goes. */
static
sigcatch (signo)
register signo;
{
	register sigbit;

	signal (signo, sigcatch);
	sigbit = 1 << signo;
resig:
	/* If it's already executing, or if the user asked to hold it,
	   then don't call the function yet. */
	if ((executing_sigs|held_sigs) & sigbit) {
		pending_sigs |= sigbit;
		return;
	}
	pending_sigs &= ~sigbit;	/* Clear pending signals */
	executing_sigs |= sigbit;	/* Say this one is executing */
	(*sigfuncs[signo]) (signo);	/* Call user function */
	executing_sigs &= ~sigbit;	/* Not executing anymore */
	if (pending_sigs & sigbit)
		goto resig;
}
#endif not BSD42