about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2021-11-28 09:50:00 -0800
committerKartik K. Agaram <vc@akkartik.com>2021-11-28 10:44:40 -0800
commit6388bc08c46c096b3df91a5deddd2ac740cd6d38 (patch)
tree0d062e5b0c00fc6fa645ed3c5621564778c9947c
parent13bfb7308a28d854c9a4685e99bf9d7ea2b2e20d (diff)
downloadteliva-6388bc08c46c096b3df91a5deddd2ac740cd6d38.tar.gz
save a snapshot of editor state across restarts
We're not using this yet.

I agonized over this decision for several weeks. Is Teliva's need to
restart with execve an utter hack or a good thing? I'm leaning towards
the latter. Constantly exercising the initial flow makes Teliva more
crash-only. We can build Steve Yegge's idea of immortality (http://steve-yegge.blogspot.com/2007/01/pinocchio-problem.html)
out of crash-only primitives, just by making reboots instantaneous. But
focusing directly on immortality tends to compromise crash-only by
exercising it more rarely.

One other issue this brings up: loading these Lua tables from disk is a
vector for arbitrary code execution. I need to fix these when I get to
sandboxing.
-rw-r--r--src/kilo.c2
-rw-r--r--src/lua.c13
2 files changed, 14 insertions, 1 deletions
diff --git a/src/kilo.c b/src/kilo.c
index b2f9a18..45d10c4 100644
--- a/src/kilo.c
+++ b/src/kilo.c
@@ -1033,6 +1033,7 @@ static void editorGo(lua_State* L) {
  * is typing stuff on the terminal. */
 static int Quit = 0;
 static int Back_to_big_picture = 0;
+extern void save_snapshot(int rowoff, int coloff, int cy, int cx);
 static void editorProcessKeypress(lua_State* L) {
     int c = getch();
     switch(c) {
@@ -1046,6 +1047,7 @@ static void editorProcessKeypress(lua_State* L) {
     case CTRL_E:
         /* Save and quit. */
         editorSaveToDisk();
+        save_snapshot(E.rowoff, E.coloff, E.cy, E.cx);
         Quit = 1;
         break;
     case CTRL_G:
diff --git a/src/lua.c b/src/lua.c
index 87a41fa..6035a62 100644
--- a/src/lua.c
+++ b/src/lua.c
@@ -398,6 +398,17 @@ static int handle_image (lua_State *L, char **argv, int n) {
 
 #define CURRENT_DEFINITION_LEN 256
 char Current_definition[CURRENT_DEFINITION_LEN+1] = {0};
+
+void save_snapshot (int rowoff, int coloff, int cy, int cx) {
+  FILE *out = fopen("teliva_snapshot", "w");
+  fprintf(out, "__teliva_snapshot = {\n");
+  fprintf(out, "  image = \"%s\", definition = \"%s\",\n", Image_name, Current_definition);
+  fprintf(out, "  rowoff = %d, coloff = %d,\n", rowoff, coloff);
+  fprintf(out, "  cy = %d, cx = %d,\n", cy, cx);
+  fprintf(out, "}\n");
+  fclose(out);
+}
+
 void save_to_current_definition_and_editor_buffer (lua_State *L, const char *definition) {
   strncpy(Current_definition, definition, CURRENT_DEFINITION_LEN);
   const char *contents = look_up_definition(L, Current_definition);
@@ -444,7 +455,7 @@ static void save_image (lua_State *L) {
   lua_getglobal(L, "teliva_program");
   int history_array = lua_gettop(L);
   int history_array_size = luaL_getn(L, history_array);
-  FILE* out = fopen(Image_name, "w");
+  FILE *out = fopen(Image_name, "w");
   fprintf(out, "teliva_program = {\n");
   for (int i = 1;  i <= history_array_size; ++i) {
     lua_rawgeti(L, history_array, i);