]> git.ozlabs.org Git - ccan-lca-2011.git/commitdiff
lca2011: slight insanity.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 25 Jan 2011 00:27:42 +0000 (10:57 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 25 Jan 2011 00:27:42 +0000 (10:57 +1030)
ccan/oserver/bin/update-parrot-to-oracle.c [new file with mode: 0755]

diff --git a/ccan/oserver/bin/update-parrot-to-oracle.c b/ccan/oserver/bin/update-parrot-to-oracle.c
new file mode 100755 (executable)
index 0000000..b62712f
--- /dev/null
@@ -0,0 +1,175 @@
+#if 0
+set -e
+OUT=`dirname "$0"`/.`basename "$0" .c`
+CCAN=/home/rusty/devel/cvs/ccan
+if [ ! -f "$OUT" ] || [ "$OUT" -ot "$0" ]; then
+    make -s -C $CCAN 
+    gcc -Wall -I$CCAN -g -o "$OUT".$$ $CCAN/ccan/talloc.o $CCAN/ccan/str.o $CCAN/ccan/str_talloc.o $CCAN/ccan/grab_file.o $CCAN/ccan/read_write_all.o $CCAN/ccan/noerr.o $CCAN/ccan/oserver.o $CCAN/ccan/tevent.o $CCAN/ccan/cdump.o -x c "$0" && mv "$OUT".$$ "$OUT"
+fi
+exec "$OUT" "$@"
+#else
+#include <ccan/talloc/talloc.h>
+#include <ccan/str/str.h>
+#include <ccan/str_talloc/str_talloc.h>
+#include <ccan/grab_file/grab_file.h>
+#include <ccan/oserver/oserver_types.h>
+#include <ccan/oserver/oserver_cdump.h>
+#include <ccan/noerr/noerr.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+
+static char *read_line(int fd)
+{
+       ssize_t len = 0;
+       char *buf = talloc_array(NULL, char, 1);
+
+       while (read(fd, buf + len, 1) == 1) {
+               if (buf[len] == '\n') {
+                       buf[len] = '\0';
+                       printf("%s\n", buf);
+                       return buf;
+               }
+               buf = talloc_realloc(NULL, buf, char, ++len + 1);
+       }
+       err(1, "Reading output");
+}
+
+#define DUMP_FILE "/var/run/oserver/dump"
+
+int main(int argc, char *argv[])
+{
+       int in[2], out[2], i, fd;
+       char *buf, *fdstr, *osnum, *str, c;
+       struct oserver *oserver = talloc(NULL, struct oserver);
+       FILE *gdbin;
+
+       /* Control a gdb. */
+       pipe(in);
+       pipe(out);
+       if (fork() == 0) {
+               close(in[1]);
+               close(out[0]);
+               dup2(in[0], STDIN_FILENO);
+               dup2(out[1], STDOUT_FILENO);
+               dup2(out[1], STDERR_FILENO);
+               execlp("gdb", "gdb", "-q", NULL);
+               exit(1);
+       }
+       close(in[0]);
+       close(out[1]);
+
+       /* In case something goes wrong... */
+       alarm(5);
+
+       /* Line-at-a-time buffering makes the code easier. */
+       gdbin = fdopen(in[1], "w");
+       setvbuf(gdbin, NULL, _IOLBF, 0);
+
+       /* Attach to the child, up stack, print something so we know you're
+        * done. */
+       fprintf(gdbin, "attach %s\n"
+               "up 10000\n"
+               "p \"end-preamble\"\n", argv[1]);
+
+       /* Throw away preamble */
+       while (!strstr(read_line(out[0]), "end-preamble"));
+
+       /* Walk ev->fd_events linked list, find add_client callback. */
+       str = talloc_strdup(NULL, "p *ev->fd_events");
+       do {
+               fprintf(gdbin, "%s\n", str);
+               buf = read_line(out[0]);
+               str = talloc_append_string(str, "->next");
+       } while (!strreg(NULL, buf, ".*add_client"));
+
+       /* ->private == oserver. */
+       fprintf(gdbin, "p (struct oserver *)$.private_data\n");
+       buf = read_line(out[0]);
+       if (!strreg(NULL, buf, "^.gdb. (\\$[0-9]+) = ", &osnum))
+               errx(1, "Could not derive oserver from '%s'", buf);
+
+       /* Populate a likely-looking oserver struct. */
+       oserver->max_clients = 0;
+       oserver->clients = talloc_array(oserver, struct client *, 5);
+       oserver->dumpfile = DUMP_FILE;
+       /* On *next* SIGHUP, we want to run the new oserver. */
+       oserver->argv_len = 3;
+       oserver->argv = talloc_array(oserver, char *, 3);
+       oserver->argv[0] = "/usr/local/bin/oserver";
+       oserver->argv[1] = "--restore";
+       oserver->argv[2] = NULL;
+       fprintf(gdbin, "p %s->fd\n", osnum);
+       buf = read_line(out[0]);
+       if (!strreg(buf, buf, "\\$[0-9]+ = ([0-9]+)", &fdstr))
+               errx(1, "Didn't get oserver fd");
+       oserver->fd = atoi(fdstr);
+
+       /* Dump the client list. */
+       for (i = 0; i < 5; i++) {
+               char *question, *answer, *sent;
+               struct client *c;
+
+               /* Print the client struct, unless ptr is NULL. */
+               fprintf(gdbin, "p %s->clients[%i] ? *%s->clients[%i] : 0\n",
+                       osnum, i, osnum, i);
+               buf = read_line(out[0]);
+               if (!strreg(oserver, buf, "fd = ([0-9]+),", &fdstr)) {
+                       oserver->clients[i] = NULL;
+                       continue;
+               }
+
+               /* Populate the client struct. */
+               oserver->max_clients = i+1;
+               oserver->clients[i] = c = talloc_zero(oserver, struct client);
+               c->fd = atoi(fdstr);
+               c->id = i;
+               c->oracle = c->subclient = -1;
+               c->question = c->answer = "";
+
+               /* Translate the states. */
+               if (strreg(buf, buf, "\\{state = SENDING_GREETING, .*bytes_sent = ([0-9]*)", &sent)) {
+                       c->state = SENDING_GREETING;
+                       c->bytes_sent = atoi(sent);
+               } else if (strreg(buf, buf, "\\{state = RECEIVING_USER_QUESTION, .*question = 0x[0-9a-f]* \"(.*)\", answer = ", &question)) {
+                       c->state = RECEIVING_USER_QUESTION;
+                       c->question = question;
+               } else if (strreg(buf, buf, "\\{state = SENDING_ANSWER_PREFIX, .*bytes_sent = ([0-9]*)", &sent)) {
+                       c->state = SENDING_ANSWER_PREFIX;
+                       c->bytes_sent = atoi(sent);
+               } else if (strreg(buf, buf, "\\{state = SENDING_ANSWER, .*answer = 0x[0-9a-f]* \"(.*)\", bytes_sent = ([0-9]*)",
+                                 &answer, &sent)) {
+                       c->state = SENDING_ANSWER;
+                       c->answer = answer;
+                       c->bytes_sent = atoi(sent);
+               } else
+                       errx(1, "Unexpected line for client %u: '%s'", i, buf);
+       }
+
+       /* Bundle up this oserver and clients into the dump file */
+       buf = cdump_bundle(NULL, cdump_struct_oserver, oserver);
+       fd = open(DUMP_FILE, O_WRONLY|O_TRUNC|O_CREAT, 0600);
+       if (fd < 0)
+               err(1, "Opening %s", DUMP_FILE);
+       write(fd, buf, strlen(buf));
+       close(fd);
+
+       /* If they didn't say --tesst, get gdb to break on main and run exec. */
+       if (!argv[2] || !streq(argv[2], "--test")) {
+               /* GDB will complain about break inside gdb-called fun, but
+                * it'll do it. */
+               fprintf(gdbin, "break main\n");
+               fprintf(gdbin, "p execl(\"/usr/local/bin/oserver\","
+                       " \"/usr/local/bin/oserver\", \"--restore\", 0)\n");
+       }
+
+       /* Detach and kill gdb. */
+       fprintf(gdbin, "detach\nquit\n");
+
+       /* Make sure it exited. */ 
+       while (read(out[0], &c, 1) == 1);
+       exit(0);
+}
+#endif