This program works in LINUX, SOLARIS, SunOS and SGI. The variations are apparent if you look at the #ifdef routines.
/*
compile with either of the two -DLINUX or -DSOLARIS flags, eg.
gcc -DLINUX test.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#if SOLARIS
#include <sys/siginfo.h>
#elif LINUX
#include <asm/sigcontext.h>
#include <asm/signal.h>
#endif
/*
#ifdef __cplusplus
extern "C" {
int mprotect(caddr_t, unsigned int, int);
int getpagesize();
#ifndef __GNUC__ // CC on SunOS needs these
int sigemptyset(sigset_t *set);
int sigaction(int sig, struct sigaction *act, struct sigaction *oact);
#endif
}
#endif
*/
#if __GNUC__ && __cplusplus
typedef void Sigfunc(...);
#else
typedef void Sigfunc();
#endif
/* ---------------------- Global variables -------------------------- */
int pageSize;
int array[20000];
/* ------------------------------------------------------------------ */
caddr_t getPage(void *ptr) {
int addr = (int)ptr;
return ((caddr_t)((addr / pageSize) * pageSize));
}
#if SUNOS
void sighandler(int sig, int code, struct sigcontext* scp, caddr_t addr) {
#elif SOLARIS
void sighandler(int sig, struct siginfo *si, int c) {
#else // e.g LINUX
void sighandler(int sig, struct sigcontext_struct scp) {
#endif
int *ptr;
#if SOLARIS
caddr_t addr = (caddr_t) si->_data._fault._addr;
#elif LINUX
caddr_t addr = (caddr_t) scp.cr2;
#endif
ptr = (int *)addr;
mprotect(getPage(addr), pageSize, PROT_READ | PROT_WRITE);
*ptr = 10;
}
Sigfunc *posixComplienceSignal(int signo, Sigfunc *func) {
struct sigaction act, oldAct;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART;
#endif
#ifdef SA_SIGINFO
act.sa_flags |= SA_SIGINFO;
#endif
if (sigaction(signo, &act, &oldAct) < 0)
return((Sigfunc *)SIG_ERR);
return(oldAct.sa_handler);
}
/* ------------------------------------------------ */
void main() {
int i;
pageSize = getpagesize();
for (i=0; i<20000; i++)
array[i] = 2;
if (posixComplienceSignal(SIGSEGV, (Sigfunc *)sighandler) == (Sigfunc *)SIG_ERR) {
perror("posixComplienceSignal:");
exit(1);
}
printf("protecting(1): %d\n", mprotect(getPage(&array[5000]), pageSize, PROT_NONE));
printf("protecting(2): %d\n", mprotect(getPage(&array[70000]), pageSize, PROT_NONE));
printf("a[2000]: %d\n", array[2000]);
printf("a[5000]: %d\n", array[5000]);
printf("a[5001]: %d\n", array[5001]);
array[7000] = 20;
printf("array[7000]: %d\n", array[7000]);
array[1000] = 30;
printf("array[10000]: %d\n", array[10000]);
}