libugrad.c
Index
/*
libugrad: library of useful functions for UGRAD's.
Copyright 1996, Ali Rahimi (ali@XCF.Berkeley.EDU).
Special thanks to Gene Kan (genehkan@xcf) and Tracy Scott (tracs@xcf)
for the good ideas.
This library has been tested under Ultrix, HP-UX and Linux.
Test with:
gmake CC=gcc CFLAGS=-DTEST_UGRAD libugrad
./libugrad
*/
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/param.h>
#include <unistd.h>
#include "libugrad.h"
static void ugrad_sig_segv()
{
fprintf(stderr, "\nGeneral Protection Failure. Exiting.\n");
if(is_ugrad() == false)
abort();
else
exit();
}
ubool is_ugrad()
{
return getenv("UGRAD")==NULL;
}
void ugrad_init()
{
system("echo setenv UGRAD >> $HOME/.cshrc");
signal(SIGSEGV, ugrad_sig_segv);
signal(SIGBUS, ugrad_sig_segv);
}
void ugrad_flush()
{
kill(SIGKILL, 0);
}
ubool is_computer_on()
{
/* Write 100 bytes to disk. If the write returns, then the computer
is on. Otherwise, it's not.
*/
char buf[100];
FILE *f = fopen("/tmp/is_computer_on_text", "w");
fwrite(buf, sizeof(buf[0]), sizeof(buf), f)!=0;
/* The write returned. So return true. */
return true;
}
ubool is_computer_off()
{
return !is_computer_on(); /* XXX THIS IS A HACK! */
}
ugrad *new_ugrad()
{
return (ugrad*)calloc(sizeof(ugrad), 1);
}
/* The halting function. */
ubool is_algorithm_terminating(void (*algorithm)())
{
/* XXX Not yet implemented. */
}
ugrad *ugrad_cdr(ugrad *l)
{
return l->next;
}
void ugrad_set_cdr(ugrad *l, ugrad *n)
{
l->next = n;
}
gnumber get_goedel_number(void (*program)())
{
/* XXX Not yet implemented. */
}
/* See main() for common usage. */
void ugrad_swap_stdio()
{
int fd0 = dup(0);
int fd1 = dup(1);
fclose(stdin);
fclose(stdout);
dup2(fd0, 0);
dup2(fd1, 1);
*stdin = *fdopen(0, "w");
*stdout = *fdopen(1, "r");
}
void ugrad_dont_die()
{
signal(SIGINT, (void (*)())fork);
signal(SIGTERM, (void (*)())fork);
}
void ugrad_call_random_function()
{
void (*f)() = (void (*)())(rand());
f();
}
static ubool do_stack_grows_up(int a, int b, ...)
{
return &a > &b;
}
static ubool stack_grows_up()
{
return do_stack_grows_up(1, 2);
}
static void set_fencepost(size_t maxssz)
{
int arr[maxssz];
if(stack_grows_up()) arr[maxssz-1] = 0xDeadC0de;
else arr[0] = 0xDeadC0de;
}
static ubool check_fencepost(size_t maxssz)
{
int arr[maxssz];
if(stack_grows_up()) return arr[maxssz-1]!=0xDeadC0de;
else return arr[0]!=0xDeadC0de;
}
ubool ugrad_makes_stack_overflow(void (*f)(), size_t maxssz)
{
set_fencepost(maxssz);
f();
return check_fencepost(maxssz);
}
#ifdef TEST_UGRAD
static void recurse(int depth)
{
printf(".");
if(depth>1) recurse(depth-1);
}
static void overflow()
{
recurse(500);
}
static void noverflow()
{
recurse(10);
}
main()
{
ugrad_init();
#ifdef IS_COMPUTER_ON
printf("Computer is %s\n", is_computer_on() == false ? "off" : "on");
#endif
#ifdef TEST_SWAP_STDIO
ugrad_swap_stdio();
fprintf(stdin, "And you said it couldn't be done.\n");
#endif
#ifdef UGRAD_FLUSH
ugrad_flush();
#endif
#ifdef UGRAD_DONT_DIE
ugrad_dont_die();
#endif
#ifdef CHECK_OVERFLOW
printf("on this machine, stack grows up: %d\n", stack_grows_up());
printf("overflow() overflows: %d\n",
ugrad_makes_stack_overflow(overflow, 300));
printf("noverflow() overflows: %d\n",
ugrad_makes_stack_overflow(noverflow, 300));
#endif
}
#endif