/* c-repl -- a C read-eval-print loop.
 * Copyright (C) 2006 Evan Martin <martine@danga.com>
 */

/* The child process is what actually runs the code.
 * It reads in a number from stdin,
 * then loads dl#.so and executes dl#().
 */

#include <assert.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static int debug = 0;

/* Load dl<id>.so and run dl<id>(). */
static void load_and_run(int id) {
  char buf[1024];

  sprintf(buf, "./dl%d.so", id);
  if (debug)
    fprintf(stderr, "CHILD> loading %s\n", buf);
  void *so = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
  if (!so) {
    fprintf(stderr, "CHILD> error loading library: %s\n", dlerror());
    assert(so);
  }

  sprintf(buf, "dl%d", id);
  void (*f)() = dlsym(so, buf);
  if (!f) {
    fprintf(stderr, "CHILD> error loading function: %s\n", dlerror());
    assert(f);
  }

  //printf("child executing '%s':\n", dlname);
  // XXX fork here to do the segfault -> undo magic?
  f();
}

int main(int argc, char **argv) {
  if (argc < 2) {
    fprintf(stderr, "bad arguments\n");
    return -1;
  }
  const int callback_pipe = atoi(argv[1]);

  char buf[1024];
  int highest_id = 0;
  while (fgets(buf, sizeof(buf), stdin)) {
    const int id = atoi(buf);
    if (id > 0)
      for ( ; highest_id < id; highest_id++)
        load_and_run(highest_id+1);

    /* If we get here, we succeeded.
     * Let the parent know. */
    const int len = strlen(buf);
    if (write(callback_pipe, buf, len) < len) {
      perror("CHILD> write");
      break;
    }
  }
  if (debug)
    fprintf(stderr, "CHILD> exiting\n");
  return 0;
};

/* vim: set ts=2 sw=2 et cino=(0 : */
