libugrad.c


Index

  • ugrad_sig_segv (returns static void )
  • is_ugrad (returns ubool )
  • ugrad_init (returns void )
  • ugrad_flush (returns void )
  • is_computer_on (returns ubool )
  • is_computer_off (returns ubool )
  • new_ugrad (returns ugrad *)
  • is_algorithm_terminating (returns ubool )
  • ugrad_cdr (returns ugrad *)
  • ugrad_set_cdr (returns void )
  • get_goedel_number (returns gnumber )
  • ugrad_swap_stdio (returns void )
  • ugrad_dont_die (returns void )
  • ugrad_call_random_function (returns void )
  • do_stack_grows_up (returns static ubool )
  • stack_grows_up (returns static ubool )
  • set_fencepost (returns static void )
  • check_fencepost (returns static ubool )
  • ugrad_makes_stack_overflow (returns ubool )
  • recurse (returns static void )
  • overflow (returns static void )
  • noverflow (returns static void )

  • /*
      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