home · contact · privacy
Client: Added checks / syntax validation for config files. Also changed commands
authorChristian Heller <c.heller@plomlompom.de>
Tue, 28 Jan 2014 03:25:45 +0000 (04:25 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 28 Jan 2014 03:25:45 +0000 (04:25 +0100)
config file format to simplify doing those checks.

confclient/commands
src/client/command_db.c
src/client/command_db.h
src/client/keybindings.c
src/client/keybindings.h
src/client/main.c
src/client/misc.c
src/client/misc.h
src/client/windows.c
src/client/windows.h
src/client/world.h

index 28ab1228b5c261686e952a08e68ac152d24541ae..50c20698d0f6333c8bc665c3f2006d62aac72da9 100644 (file)
-wait wait 0 wait / next turn
-use use i use selected inventory object
-drop drop i drop object from inventory
-pick pick_up 0 pick up object from ground
-player_u move N player up
-player_d move S player down
-player_l move W player left
-player_r move E player right
-quit 0 0 quit
-to_g_keywin 0 0 toggle global keys window
-to_mapwin 0 0 toggle map window
-to_infowin 0 0 toggle info window
-to_logwin 0 0 toggle log window
-to_wg_keywin 0 0 toggle window geometry keys window
-to_wk_keywin 0 0 toggle window keybinding keys window
-cyc_win_f 0 0 cycle window selection forwards
-winconf 0 0 toggle window configuration view
-cyc_win_b 0 0 cycle window selection backwards
-scrl_l 0 0 scroll pad left
-scrl_r 0 0 scroll pad right
-g_keys_d 0 0 global keybindings nav down
-g_keys_u 0 0 global keybindings nav up
-g_keys_m 0 0 global keybindings modify
-shift_f 0 0 shift window forwards
-shift_b 0 0 shift window backwards
-grow_h 0 0 grow window horizontally
-shri_h 0 0 shrink window horizontally
-grow_v 0 0 grow window vertically
-shri_v 0 0 shrink window vertically
-to_height_t 0 0 toggle window height type
-to_width_t 0 0 toggle window width type
-w_keys_d 0 0 win keys nav down
-w_keys_u 0 0 win keys nav up
-w_keys_m 0 0 win keys mod
-wg_keys_d 0 0 win geometry config keybindings nav down
-wg_keys_u 0 0 win geometry config keybindings nav up
-wg_keys_m 0 0 win geometry config keybindings modify
-wk_keys_d 0 0 win keybindings config keybindings nav down
-wk_keys_u 0 0 win keybindings config keybindings nav up
-wk_keys_m 0 0 win keybindings config keybindings modify
-reload_conf 0 0 reload windows and keybindings configuration
-save_conf 0 0 save windows and keybindings
-map_u 0 0 map up
-map_d 0 0 map down
-map_l 0 0 map left
-map_r 0 0 map right
-map_c 0 0 map center player
-to_a_keywin 0 0 toggle view of available keybindings
-to_inv 0 0 toggle inventory window
-inv_d 0 0 inventory selection down
-inv_u 0 0 inventory selection up
+wait
+wait / next turn
+wait
+0
+%
+player_u
+player up
+move
+N
+%
+player_d
+player down
+move
+S
+%
+player_l
+player left
+move
+W
+%
+player_r
+player right
+move
+E
+%
+pick
+pick up object from ground
+pick_up
+0
+%
+use
+use selected inventory object
+use
+i
+%
+drop
+drop object from inventory
+drop
+i
+%
+quit
+quit
+%
+cyc_win_f
+cycle window selection forwards
+%
+cyc_win_b
+cycle window selection backwards
+%
+shift_f
+shift window forwards
+%
+shift_b
+shift window backwards
+%
+scrl_l
+scroll pad left
+%
+scrl_r
+scroll pad right
+%
+g_keys_d
+global keybindings nav down
+%
+g_keys_u
+global keybindings nav up
+%
+g_keys_m
+global keybindings modify
+%
+winconf
+toggle window configuration view
+%
+grow_h
+grow window horizontally
+%
+shri_h
+shrink window horizontally
+%
+grow_v
+grow window vertically
+%
+shri_v
+shrink window vertically
+%
+to_height_t
+toggle window height type
+%
+to_width_t
+toggle window width type
+%
+inv_d
+inventory selection down
+%
+inv_u
+inventory selection up
+%
+w_keys_d
+win keys nav down
+%
+w_keys_u
+win keys nav up
+%
+w_keys_m
+win keys mod
+%
+wg_keys_d
+win geometry config keybindings nav down
+%
+wg_keys_u
+win geometry config keybindings nav up
+%
+wg_keys_m
+win geometry config keybindings modify
+%
+wk_keys_d
+win keybindings config keybindings nav down
+%
+wk_keys_u
+win keybindings config keybindings nav up
+%
+wk_keys_m
+win keybindings config keybindings modify
+%
+reload_conf
+reload windows and keybindings configuration
+%
+save_conf
+save windows and keybindings
+%
+map_u
+map up
+%
+map_d
+map down
+%
+map_l
+map left
+%
+map_r
+map right
+%
+map_c
+map center player
+%
+to_a_keywin
+toggle view of available keybindings
+%
+to_inv
+toggle inventory window
+%
+to_g_keywin
+toggle global keys window
+%
+to_mapwin
+toggle map window
+%
+to_infowin
+toggle info window
+%
+to_logwin
+toggle log window
+%
+to_wg_keywin
+toggle window geometry keys window
+%
+to_wk_keywin
+toggle window keybinding keys window
+%
index 19cd4064e09c7878d49d841ed1e86d30536ffc58..57ea2f344acb60e531b529fc5fe11e618b98c639 100644 (file)
@@ -5,50 +5,24 @@
 #include <stdint.h> /* uint8_t, uint32_t */
 #include <stdio.h> /* FILE, sprintf() */
 #include <stdlib.h> /* free() */
 #include <stdint.h> /* uint8_t, uint32_t */
 #include <stdio.h> /* FILE, sprintf() */
 #include <stdlib.h> /* free() */
-#include <string.h> /* memcpy(), strlen(), strtok(), strcmp() */
-#include "../common/readwrite.h" /* try_fopen(), try_fclose(), try_fgets()
-                                  * textfile_sizes()
-                                  */
-#include "../common/rexit.h" /* for exit_err() */
+#include <string.h> /* memset(), strlen(), strcmp() */
+#include "../common/readwrite.h" /* try_fopen(),try_fclose(),textfile_sizes() */
+#include "../common/rexit.h" /* exit_trouble() */
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "../common/try_malloc.h" /* try_malloc() */
-#include "cleanup.h" /* set_cleanup_flag() */
+#include "err_try_fgets.h" /* reset_err_try_fgets_counter() */
 #include "misc.h" /* array_append() */
 #include "world.h" /* global world */
 #include "misc.h" /* array_append() */
 #include "world.h" /* global world */
+#include "cleanup.h" /* set_cleanup_flag() */
 
 
 
 
 
 
-/* Helpers to init_command_db(). */
-static uint8_t copy_tokenized_string(char * line, char ** ch_ptr, char * delim);
-static char * init_command_db_err(char * line_copy, uint8_t line_number);
-
-
-static uint8_t copy_tokenized_string(char * line, char ** ch_ptr, char * delim)
-{
-    char * f_name = "copy_tokenized_string()";
-    char * dsc_ptr = strtok(line, delim);
-    if (!dsc_ptr)
-    {
-        return 1;
-    }
-    * ch_ptr = try_malloc(strlen(dsc_ptr) + 1, f_name);
-    memcpy(* ch_ptr, dsc_ptr, strlen(dsc_ptr) + 1);
-    return 0;
-}
-
-
-
-static char * init_command_db_err(char * line_copy, uint8_t line_number)
+/* Helper to init_command_db(). */
+static void write_line_to_target(char ** target, char * line)
 {
 {
-    char * f_name = "init_command_db_err";
-    char * err_start = "Failed reading command config file at ";
-    char * err_middle = " due to malformed line ";
-    line_copy[strlen(line_copy) - 1] = '\0';
-    char * err = try_malloc(strlen(err_start) + strlen(world.path_commands) +
-                            strlen(err_middle) + 3 + 2 + strlen(line_copy) + 1,
-                            f_name);
-    sprintf(err, "%s%s%s%d: %s", err_start, world.path_commands, err_middle,
-            line_number, line_copy);
-    return err;
+    char * f_name = "write_line_to_target()";
+    *target = try_malloc(strlen(line), f_name);
+    line[strlen(line) - 1] = '\0';
+    sprintf(*target, "%s", line);
 }
 
 
 }
 
 
@@ -61,16 +35,12 @@ extern struct Command * get_command(char * dsc_short)
     {
         if (0 == strcmp(dsc_short, cmd_ptr->dsc_short))
         {
     {
         if (0 == strcmp(dsc_short, cmd_ptr->dsc_short))
         {
-            break;
+            return cmd_ptr;
         }
         cmd_ptr = &cmd_ptr[1];
         i++;
     }
         }
         cmd_ptr = &cmd_ptr[1];
         i++;
     }
-    char * err_start = "get_command_data() failed on request for: ";
-    char err[strlen(err_start) + strlen(dsc_short) + 1];
-    sprintf(err, "%s%s", err_start, dsc_short);
-    exit_err(i == world.commandDB.n, err);
-    return cmd_ptr;
+    return NULL;
 }
 
 
 }
 
 
@@ -78,34 +48,34 @@ extern struct Command * get_command(char * dsc_short)
 extern void init_command_db()
 {
     char * f_name = "init_command_db()";
 extern void init_command_db()
 {
     char * f_name = "init_command_db()";
+    char * context = "Failed reading command DB file. ";
     FILE * file = try_fopen(world.path_commands, "r", f_name);
     FILE * file = try_fopen(world.path_commands, "r", f_name);
-    uint32_t lines;
-    uint32_t linemax = textfile_sizes(file, &lines);
+    uint32_t linemax = textfile_sizes(file, NULL);
     char line[linemax + 1];
     char line[linemax + 1];
+    reset_err_try_fgets_counter();
     uint8_t i = 0;
     uint8_t i = 0;
-    char * delim = " ";
-    while (try_fgets(line, linemax + 1, file, f_name))
+    while (1)
     {
     {
-        if ('\n' == line[0] || 0 == line[0])
+        int test_for_end = try_fgetc(file, f_name);
+        if (EOF == test_for_end || '\n' == test_for_end)
         {
             break;
         }
         {
             break;
         }
-        char line_copy[strlen(line) + 1];
-        sprintf(line_copy, "%s", line);
+        exit_trouble(EOF == ungetc(test_for_end, file), f_name, "ungetc()");
         struct Command cmd;
         struct Command cmd;
-        char * arg_string;
-        exit_err((  copy_tokenized_string(line, &cmd.dsc_short, delim)
-                 || copy_tokenized_string(NULL, &cmd.server_msg, delim)
-                 || NULL == (arg_string = strtok(NULL, delim))
-                 || strlen(arg_string) > 1
-                 || copy_tokenized_string(NULL, &cmd.dsc_long, "\n")),
-                 init_command_db_err(line_copy, i + 1));
-        cmd.arg = arg_string[0];
-        if (!strcmp("0", cmd.server_msg))
-        {                          /* A .server_msg == NULL helps control.c's */
-            free(cmd.server_msg);  /* try_key() and try_server_command() to   */
-            cmd.server_msg = NULL; /* differentiate server commands from      */
-        }                          /* non-server commands.                    */
+        memset(&cmd, 0, sizeof(struct Command));
+        err_try_fgets(line, linemax, file, context, "nf");
+        write_line_to_target(&cmd.dsc_short, line);
+        err_try_fgets(line, linemax, file, context, "0nf");
+        write_line_to_target(&cmd.dsc_long, line);
+        err_try_fgets(line, linemax, file, context, "0nf");
+        if (strcmp(world.delim, line))
+        {
+            write_line_to_target(&cmd.server_msg, line);
+            err_try_fgets(line, linemax, file, context, "0nfs");
+            cmd.arg = line[0];
+            err_try_fgets(line, linemax, file, context, "d");
+        }
         array_append(i, sizeof(struct Command), (void *) &cmd,
                      (void **) &world.commandDB.cmds);
         i++;
         array_append(i, sizeof(struct Command), (void *) &cmd,
                      (void **) &world.commandDB.cmds);
         i++;
index 566bf70b3f7abb2c9e6a52dff25fec817db8c432..e20d16d03b8d9173baa730d5f60e47ad749dafb4 100644 (file)
@@ -28,7 +28,9 @@ struct CommandDB
 
 
 
 
 
 
-/* Return Command struct for command described by its "dsc_short" member. */
+/* Return Command struct for command described by its "dsc_short" member. Return
+ * NULL if no such command is found.
+ */
 extern struct Command * get_command(char * dsc_short);
 
 /* Reads in CommandDB config file line by line until end or first empty line. */
 extern struct Command * get_command(char * dsc_short);
 
 /* Reads in CommandDB config file line by line until end or first empty line. */
index 857cd50b9f6c787008c2cb5c90abae31bc7c35d0..eb67f26755b3967a5b06b6c497278e42af218a5b 100644 (file)
@@ -3,12 +3,14 @@
 #include "keybindings.h"
 #include <ncurses.h> /* keycode defines, cbreak(), halfdelay(), getch() */
 #include <stddef.h> /* NULL */
 #include "keybindings.h"
 #include <ncurses.h> /* keycode defines, cbreak(), halfdelay(), getch() */
 #include <stddef.h> /* NULL */
-#include <stdio.h> /* FILE, sprintf(), snprintf() */
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t */
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t */
+#include <stdio.h> /* FILE, sprintf() */
 #include <stdlib.h> /* free(), atoi() */
 #include <string.h> /* strlen(), strchr(), strcmp() */
 #include <stdlib.h> /* free(), atoi() */
 #include <string.h> /* strlen(), strchr(), strcmp() */
-#include "../common/readwrite.h" /* textfile_sizes(), try_fgets(),try_fwrite()*/
+#include "../common/readwrite.h" /* try_fwrite()*/
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "../common/try_malloc.h" /* try_malloc() */
+#include "command_db.h" /* get_command() */
+#include "err_try_fgets.h" /* err_try_fgets(), err_line() */
 #include "windows.h" /* draw_all_wins() */
 #include "world.h" /* global world */
 
 #include "windows.h" /* draw_all_wins() */
 #include "world.h" /* global world */
 
@@ -158,8 +160,7 @@ extern char * get_keyname_to_keycode(uint16_t keycode)
 
 
 
 
 
 
-extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd,
-                                      char * delim)
+extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd)
 {
     char * f_name = "write_keybindings_to_file()";
     uint16_t linemax = 0;
 {
     char * f_name = "write_keybindings_to_file()";
     uint16_t linemax = 0;
@@ -181,7 +182,7 @@ extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd,
         try_fwrite(line, sizeof(char), strlen(line), file, f_name);
         kb_p = kb_p->next;
     }
         try_fwrite(line, sizeof(char), strlen(line), file, f_name);
         kb_p = kb_p->next;
     }
-    try_fwrite(delim, strlen(delim), 1, file, f_name);
+    try_fwrite(world.delim, strlen(world.delim), 1, file, f_name);
 }
 
 
 }
 
 
@@ -190,22 +191,38 @@ extern void read_keybindings_from_file(char * line, uint32_t linemax,
                                        FILE * file, struct KeyBindingDB * kbd)
 {
     char * f_name = "read_keybindings_from_file()";
                                        FILE * file, struct KeyBindingDB * kbd)
 {
     char * f_name = "read_keybindings_from_file()";
-    char * cmdptr;
+    char * context = "Failed reading keybindings from interface config file. ";
+    char * err_space    = "Line illegally ends in whitespace.";
+    char * err_nospace  = "No whitespace found in line.";
+    char * err_int      = "Line starts not with a decimal number in digits.";
+    char * err_toolarge = "Keycode number too large, must be below 1000.";
+    char * err_cmd      = "No such command in command DB.";
     struct KeyBinding ** loc_last_ptr = &kbd->kbs;
     * loc_last_ptr = 0;
     struct KeyBinding ** loc_last_ptr = &kbd->kbs;
     * loc_last_ptr = 0;
-    while (try_fgets(line, linemax + 1, file, f_name))
+    while (1)
     {
     {
-        if (!strcmp("%\n", line))
+        err_try_fgets(line, linemax, file, context, "0nf");
+        if (!strcmp(world.delim, line))
         {
             break;
         }
         {
             break;
         }
+        err_line(' ' == line[strlen(line) - 2], line, context, err_space);
+        char * ptr_space;
+        err_line(!(ptr_space = strchr(line, ' ')), line, context, err_nospace);
+        uint8_t i = 0;
+        err_line(0 == (ptr_space - line), line, context, err_int);
+        for (; i < (ptr_space - line); i++)
+        {
+            err_line(line[i] < '0' || '9' < line[i], line, context, err_int);
+        }
+        err_line(i > 3, line, context, err_toolarge);
         * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), f_name);
         struct KeyBinding * kb_p = * loc_last_ptr;
         * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), f_name);
         struct KeyBinding * kb_p = * loc_last_ptr;
+        line[strlen(line) - 1] = '\0';
+        kb_p->command = get_command(ptr_space + 1);
+        err_line(!(kb_p->command), line, context, err_cmd);
         kb_p->next = 0;
         kb_p->key = atoi(line);
         kb_p->next = 0;
         kb_p->key = atoi(line);
-        cmdptr = strchr(line, ' ') + 1;
-        cmdptr[strlen(cmdptr) - 1] = '\0';
-        kb_p->command = get_command(cmdptr);
         loc_last_ptr = & kb_p->next;
     }
 }
         loc_last_ptr = & kb_p->next;
     }
 }
index d0cc001e2254749dcc9ea501c765260ef0e400bf..ff89a4cadee19b87a7ae641546f58de613d2e245 100644 (file)
@@ -37,9 +37,8 @@ extern struct Command * get_command_to_keycode(struct KeyBinding * kb_p,
  */
 extern char * get_keyname_to_keycode(uint16_t keycode);
 
  */
 extern char * get_keyname_to_keycode(uint16_t keycode);
 
-/* Read/write from/to "file" "kbd", delimited by "delim". */
-extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd,
-                                      char * delim);
+/* Read/write from/to "file" "kbd", delimited by world.delim. */
+extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd);
 extern void read_keybindings_from_file(char * line, uint32_t linemax,
                                        FILE * file, struct KeyBindingDB * kbd);
 
 extern void read_keybindings_from_file(char * line, uint32_t linemax,
                                        FILE * file, struct KeyBindingDB * kbd);
 
index c7ac6f1a94a771f36577f899e68581bd0bd85124..6599d624701f426af133fca1bff768a41789c968 100644 (file)
@@ -5,12 +5,13 @@
 #include <stddef.h> /* NULL */
 #include <stdlib.h> /* exit() */
 #include <string.h> /* memset() */
 #include <stddef.h> /* NULL */
 #include <stdlib.h> /* exit() */
 #include <string.h> /* memset() */
-#include "../common/rexit.h" /* set_cleanup_func(), exit_trouble() */
+#include <unistd.h> /* access() */
+#include "../common/rexit.h" /* set_cleanup_func(), exit_trouble(),exit_err() */
 #include "cleanup.h" /* cleanup(), set_cleanup_flag() */
 #include "command_db.h" /* init_command_db() */
 #include "io.h" /* io_loop(), try_send() */
 #include "misc.h" /* load_interface_conf(), winch_called() */
 #include "cleanup.h" /* cleanup(), set_cleanup_flag() */
 #include "command_db.h" /* init_command_db() */
 #include "io.h" /* io_loop(), try_send() */
 #include "misc.h" /* load_interface_conf(), winch_called() */
-#include "windows.h" /* struct Win, winch_called() */
+#include "windows.h" /* winch_called() */
 #include "world.h" /* struct World */
 
 
 #include "world.h" /* struct World */
 
 
@@ -23,10 +24,12 @@ int main(int argc, char * argv[])
 {
     char * f_name = "main()";
 
 {
     char * f_name = "main()";
 
-    /* Declare hard-coded paths here. */
-    world.path_server_in      = "server/in";
-    world.path_commands       = "confclient/commands";
-    world.path_interface_conf = "confclient/interface_conf";
+    /* Declare hard-coded paths and values here. */
+    world.path_server_in  = "server/in";
+    world.path_commands   = "confclient/commands";
+    world.path_interface  = "confclient/interface_conf";
+    world.winDB.legal_ids = "012ciklm";
+    world.delim           = "%\n";
 
     /* Parse command line arguments. */
     obey_argv(argc, argv);
 
     /* Parse command line arguments. */
     obey_argv(argc, argv);
@@ -34,6 +37,10 @@ int main(int argc, char * argv[])
     /* So error exits also go through the client's cleanup() function. */
     set_cleanup_func(cleanup);
 
     /* So error exits also go through the client's cleanup() function. */
     set_cleanup_func(cleanup);
 
+    /* Check existence of config files. */
+    exit_err(access(world.path_commands, F_OK), "No commands config file.");
+    exit_err(access(world.path_interface, F_OK), "No interface config file.");
+
     /* Initialize the whole interface. */
     world.winDB.t_screen = initscr();
     set_cleanup_flag(CLEANUP_NCURSES);
     /* Initialize the whole interface. */
     world.winDB.t_screen = initscr();
     set_cleanup_flag(CLEANUP_NCURSES);
index 4f967dfdcbf764b6e5854f687664fcbe7426e05c..3bcd784a601c599ed488daaa4593d62eababbe33 100644 (file)
@@ -1,28 +1,30 @@
 /* src/client/misc.c */
 
 #include "misc.h"
 /* src/client/misc.c */
 
 #include "misc.h"
-#include <stdlib.h> /* exit() */
 #include <ncurses.h> /* delwin() */
 #include <stddef.h> /* NULL */
 #include <stdint.h> /* uint8_t, uint32_t */
 #include <ncurses.h> /* delwin() */
 #include <stddef.h> /* NULL */
 #include <stdint.h> /* uint8_t, uint32_t */
-#include <stdio.h> /* sprintf() */
-#include <string.h> /* strlen() */
+#include <stdio.h> /* FILE, sprintf() */
+#include <stdlib.h> /* free(), exit() */
+#include <string.h> /* memcpy(), strlen() */
 #include <unistd.h> /* global optarg, getopt() */
 #include "../common/readwrite.h" /* try_fopen(), try_fclose(), textfile_sizes(),
                                   * try_fclose_unlink_rename(),
                                   */
 #include <unistd.h> /* global optarg, getopt() */
 #include "../common/readwrite.h" /* try_fopen(), try_fclose(), textfile_sizes(),
                                   * try_fclose_unlink_rename(),
                                   */
+#include "../common/rexit.h" /* exit_err() */
+#include "../common/try_malloc.h" /* try_malloc() */
 #include "cleanup.h" /* set_cleanup_flag() */
 #include "cleanup.h" /* set_cleanup_flag() */
+#include "err_try_fgets.h" /* reset_err_try_fgets_counter() */
 #include "keybindings.h" /* free_keybindings(), read_keybindings_from_file(),
                           * write_keybindings_to_file()
                           */
 #include "map_window.h" /* map_center() */
 #include "keybindings.h" /* free_keybindings(), read_keybindings_from_file(),
                           * write_keybindings_to_file()
                           */
 #include "map_window.h" /* map_center() */
-#include "windows.h" /* for free_winDB(), make_v_screen_and_init_win_sizes(),
+#include "windows.h" /* free_winDB(), make_v_screen_and_init_win_sizes(),
                       * read_winconf_from_file(), write_winconf_of_id_to_file(),
                       * toggle_window()
                       */
 #include "world.h" /* global world */
 
                       * read_winconf_from_file(), write_winconf_of_id_to_file(),
                       * toggle_window()
                       */
 #include "world.h" /* global world */
 
-#include "../common/try_malloc.h" /* try_malloc() */
 
 
 extern void obey_argv(int argc, char * argv[])
 
 
 extern void obey_argv(int argc, char * argv[])
@@ -32,7 +34,7 @@ extern void obey_argv(int argc, char * argv[])
     {
         if      ('i' == opt)
         {
     {
         if      ('i' == opt)
         {
-            world.path_interface_conf = optarg;
+            world.path_interface = optarg;
         }
         else
         {
         }
         else
         {
@@ -46,19 +48,18 @@ extern void obey_argv(int argc, char * argv[])
 extern void save_interface_conf()
 {
     char * f_name = "save_interface_conf()";
 extern void save_interface_conf()
 {
     char * f_name = "save_interface_conf()";
-    char * path = world.path_interface_conf;
+    char * path = world.path_interface;
     char path_tmp[strlen(path) + 4 + 1];
     sprintf(path_tmp, "%s_tmp", path);
     FILE * file = try_fopen(path_tmp, "w", f_name);
     char path_tmp[strlen(path) + 4 + 1];
     sprintf(path_tmp, "%s_tmp", path);
     FILE * file = try_fopen(path_tmp, "w", f_name);
-    char * delim = "%\n";
-    write_keybindings_to_file(file, &world.kb_global, delim);
-    write_keybindings_to_file(file, &world.kb_wingeom, delim);
-    write_keybindings_to_file(file, &world.kb_winkeys, delim);
-    write_order_wins_visible_active(file, delim);
+    write_keybindings_to_file(file, &world.kb_global);
+    write_keybindings_to_file(file, &world.kb_wingeom);
+    write_keybindings_to_file(file, &world.kb_winkeys);
+    write_order_wins_visible_active(file);
     uint8_t i;
     for (i = 0; i < strlen(world.winDB.ids); i++)
     {
     uint8_t i;
     for (i = 0; i < strlen(world.winDB.ids); i++)
     {
-        write_winconf_of_id_to_file(file, world.winDB.ids[i], delim);
+        write_winconf_of_id_to_file(file, world.winDB.ids[i]);
     }
     try_fclose_unlink_rename(file, path_tmp, path, f_name);
 }
     }
     try_fclose_unlink_rename(file, path_tmp, path, f_name);
 }
@@ -70,23 +71,35 @@ extern void load_interface_conf()
     char * f_name = "load_interface_conf()";
 
     /* Read keybindings and WincConf DB from interface config file. */
     char * f_name = "load_interface_conf()";
 
     /* Read keybindings and WincConf DB from interface config file. */
-    FILE * file = try_fopen(world.path_interface_conf, "r", f_name);
+    reset_err_try_fgets_counter();
+    FILE * file = try_fopen(world.path_interface, "r", f_name);
     uint32_t linemax = textfile_sizes(file, NULL);
     char line[linemax + 1];
     read_keybindings_from_file(line, linemax, file, &world.kb_global);
     read_keybindings_from_file(line, linemax, file, &world.kb_wingeom);
     read_keybindings_from_file(line, linemax, file, &world.kb_winkeys);
     uint32_t linemax = textfile_sizes(file, NULL);
     char line[linemax + 1];
     read_keybindings_from_file(line, linemax, file, &world.kb_global);
     read_keybindings_from_file(line, linemax, file, &world.kb_wingeom);
     read_keybindings_from_file(line, linemax, file, &world.kb_winkeys);
-    read_order_wins_visible_active(line, linemax, file);
+    char active_tmp;
+    char * order_tmp;
+    read_order_wins_visible_active(line, linemax, file, &order_tmp, &active_tmp);
     while (read_winconf_from_file(line, linemax, file));
     try_fclose(file, f_name);
 
     while (read_winconf_from_file(line, linemax, file));
     try_fclose(file, f_name);
 
+    /* Check that windows of all legal IDs have been initalized. The validity of
+     * this test relies on read_winconf_from_file() failing on duplicates. Only
+     * on success initialize the windows as visible, to enable safe cleaning up.
+     */
+    char * err = "Failed to initialize all expected windows.";
+    exit_err(strlen(world.winDB.legal_ids) != strlen(world.winDB.ids), err);
+    world.winDB.active = active_tmp;
+    world.winDB.order = order_tmp;
+
     /* Build windows as defined by read interface data and toggle them on. */
     make_v_screen_and_init_win_sizes();
     /* Build windows as defined by read interface data and toggle them on. */
     make_v_screen_and_init_win_sizes();
-    uint8_t i;
     char tmp_active = world.winDB.active;
     char tmp_order[strlen(world.winDB.order) + 1];
     sprintf(tmp_order, "%s", world.winDB.order);
     world.winDB.order[0] = '\0';
     char tmp_active = world.winDB.active;
     char tmp_order[strlen(world.winDB.order) + 1];
     sprintf(tmp_order, "%s", world.winDB.order);
     world.winDB.order[0] = '\0';
+    uint8_t i;
     for (i = 0; i < strlen(tmp_order); toggle_window(tmp_order[i]), i++);
     world.winDB.active = tmp_active;
 
     for (i = 0; i < strlen(tmp_order); toggle_window(tmp_order[i]), i++);
     world.winDB.active = tmp_active;
 
index 30f171027bdc76e53acf5a8e26cbc326f8fcf0b2..928d8db86e70193cb01fb93434319cc7e9de7e2d 100644 (file)
@@ -36,4 +36,5 @@ extern void array_append(uint32_t old_n, size_t region_size, void * new_region,
                          void ** ptr_old_array);
 
 
                          void ** ptr_old_array);
 
 
+
 #endif
 #endif
index ee74528f80c66271c7fe7e484875f525de4a18a6..cd3ad8ced7805fc5f2f7fcecc868b2948935a6e5 100644 (file)
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t, UINT16_MAX */
 #include <stdio.h> /* sprintf() */
 #include <string.h> /* memcpy(), strlen(), strnlen(), strchr(), memset() */
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t, UINT16_MAX */
 #include <stdio.h> /* sprintf() */
 #include <string.h> /* memcpy(), strlen(), strnlen(), strchr(), memset() */
+#include "../common/readwrite.h" /* try_fputc(), try_write(), try_fgetc() */
 #include "../common/rexit.h" /* exit_trouble(), exit_err() */
 #include "../common/rexit.h" /* exit_trouble(), exit_err() */
-#include "../common/readwrite.h" /* try_fputc(), try_write(), try_fgets(),
-                                  * try_fgetc()
-                                  */
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "../common/yx_uint16.h" /* struct yx_uint16 */
 #include "draw_wins.h" /* draw_winconf_geometry(), draw_winconf_keybindings(),
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "../common/yx_uint16.h" /* struct yx_uint16 */
 #include "draw_wins.h" /* draw_winconf_geometry(), draw_winconf_keybindings(),
@@ -24,6 +22,7 @@
                         * draw_win_keybindings_winconf_geometry(),
                         * draw_win_keybindings_global()
                         */
                         * draw_win_keybindings_winconf_geometry(),
                         * draw_win_keybindings_global()
                         */
+#include "err_try_fgets.h" /* err_try_fgets(), err_line() */
 #include "keybindings.h" /* free_keybindings(), write_keybidings_to_file(),
                           * read_keybindings_from_file()
                           */
 #include "keybindings.h" /* free_keybindings(), write_keybidings_to_file(),
                           * read_keybindings_from_file()
                           */
@@ -595,23 +594,31 @@ extern uint8_t read_winconf_from_file(char * line, uint32_t linemax,
                                       FILE * file)
 {
     char * f_name = "read_winconf_from_file()";
                                       FILE * file)
 {
     char * f_name = "read_winconf_from_file()";
-    int test = try_fgetc(file, f_name);
-    if (EOF == test || '\n' == test)
+    char * context = "Failed reading individual window's configuration from "
+                     "interface config file. ";
+    char * err_id  = "Illegal ID(s) selected.";
+    char * err_2   = "Double-initialized window.";
+    int test_for_end = try_fgetc(file, f_name);
+    if (EOF == test_for_end || '\n' == test_for_end)
     {
         return 0;
     }
     {
         return 0;
     }
+    exit_trouble(EOF == ungetc(test_for_end, file), f_name, "ungetc()");
+    err_try_fgets(line, linemax, file, context, "ns");
+    err_line(NULL == strchr(world.winDB.legal_ids, line[0]), line, context,
+             err_id);
+    exit_err(world.winDB.ids && NULL!=strchr(world.winDB.ids, line[0]), err_2);
     struct Win win;
     memset(&win, 0, sizeof(struct Win));
     struct Win win;
     memset(&win, 0, sizeof(struct Win));
-    win.id = (char) test;
-    try_fgetc(file, f_name);
-    try_fgets(line, linemax + 1, file, f_name);
+    win.id = (char) line[0];
+    err_try_fgets(line, linemax, file, context, "0n");
     win.title = try_malloc(strlen(line), f_name);
     win.title = try_malloc(strlen(line), f_name);
-    memcpy(win.title, line, strlen(line) - 1);  /* Eliminate newline char */
-    win.title[strlen(line) - 1] = '\0';         /* char at end of string. */
-    try_fgets(line, linemax + 1, file, f_name);
+    memcpy(win.title, line, strlen(line) - 1);      /* Eliminate newline char */
+    win.title[strlen(line) - 1] = '\0';             /* char at end of string. */
+    err_try_fgets(line, linemax, file, context, "0ni");
     win.target_height = atoi(line);
     win.target_height_type = (0 >= win.target_height);
     win.target_height = atoi(line);
     win.target_height_type = (0 >= win.target_height);
-    try_fgets(line, linemax + 1, file, f_name);
+    err_try_fgets(line, linemax, file, context, "0ni");
     win.target_width = atoi(line);
     win.target_width_type = (0 >= win.target_width);
     read_keybindings_from_file(line, linemax, file, &win.kb);
     win.target_width = atoi(line);
     win.target_width_type = (0 >= win.target_width);
     read_keybindings_from_file(line, linemax, file, &win.kb);
@@ -635,7 +642,7 @@ extern uint8_t read_winconf_from_file(char * line, uint32_t linemax,
 
 
 
 
 
 
-extern void write_winconf_of_id_to_file(FILE * file, char c, char * delim)
+extern void write_winconf_of_id_to_file(FILE * file, char c)
 {
     char * f_name = "write_winconf_of_id_to_file()";
     struct Win * wc = get_win_by_id(c);
 {
     char * f_name = "write_winconf_of_id_to_file()";
     struct Win * wc = get_win_by_id(c);
@@ -653,38 +660,53 @@ extern void write_winconf_of_id_to_file(FILE * file, char c, char * delim)
     try_fwrite(line, sizeof(char), strlen(line), file, f_name);
     sprintf(line, "%d\n", wc->target_width);
     try_fwrite(line, sizeof(char), strlen(line), file, f_name);
     try_fwrite(line, sizeof(char), strlen(line), file, f_name);
     sprintf(line, "%d\n", wc->target_width);
     try_fwrite(line, sizeof(char), strlen(line), file, f_name);
-    write_keybindings_to_file(file, &wc->kb, delim);
+    write_keybindings_to_file(file, &wc->kb);
 }
 
 
 
 extern void read_order_wins_visible_active(char * line, uint32_t linemax,
 }
 
 
 
 extern void read_order_wins_visible_active(char * line, uint32_t linemax,
-                                           FILE * file)
+                                           FILE * file, char ** tmp_order,
+                                           char * tmp_active)
 {
     char * f_name = "read_order_wins_visible_active()";
 {
     char * f_name = "read_order_wins_visible_active()";
-    char win_order[linemax + 1];
-    try_fgets(win_order, linemax + 1, file, f_name);
-    win_order[strlen(win_order) - 1] = '\0';
-    world.winDB.order = try_malloc(strlen(win_order) + 1, f_name);
-    sprintf(world.winDB.order, "%s", win_order);
-    int char_or_eof = try_fgetc(file, f_name);
-    char * err_eof = "fgetc() unexpectedly hitting EOF";
-    exit_trouble(EOF == char_or_eof, f_name, err_eof);
-    world.winDB.active = (uint8_t) char_or_eof;
-    exit_trouble(EOF == try_fgetc(file, f_name), f_name, err_eof);
-    try_fgets(line, linemax + 1, file, f_name);
+    char * context   = "Failed reading order and activation of visible windows "
+                       "from interface config file. ";
+    char * err_id    = "Illegal ID(s) selected.";
+    err_try_fgets(line, linemax, file, context, "01");
+    uint32_t i = 0;
+    for (; i < strlen(line) - 1; i++)
+    {
+        char * test = strchr(world.winDB.legal_ids, line[i]);
+        err_line(!test, line, context, err_id);
+    }
+    line[strlen(line) - 1] = '\0';
+    *tmp_order = try_malloc(strlen(line) + 1, f_name);
+    sprintf(*tmp_order, "%s", line);
+    if (*tmp_order[0])
+    {
+        err_try_fgets(line, linemax, file, context, "0nfs");
+        err_line(NULL == strchr(*tmp_order, line[0]), line, context, err_id);
+        *tmp_active = line[0];
+    }
+    else
+    {
+        err_try_fgets(line, linemax, file, context, "0ne");
+        *tmp_active = '\0';
+    }
+    err_try_fgets(line, linemax, file, context, "d");
 }
 
 
 
 }
 
 
 
-extern void write_order_wins_visible_active(FILE * file, char * delim)
+extern void write_order_wins_visible_active(FILE * file)
 {
     char * f_name = "write_order_wins_visible_active()";
     try_fwrite(world.winDB.order, strlen(world.winDB.order), 1, file, f_name);
     try_fputc('\n', file, f_name);
     try_fputc(world.winDB.active, file, f_name);
     try_fputc('\n', file, f_name);
 {
     char * f_name = "write_order_wins_visible_active()";
     try_fwrite(world.winDB.order, strlen(world.winDB.order), 1, file, f_name);
     try_fputc('\n', file, f_name);
     try_fputc(world.winDB.active, file, f_name);
     try_fputc('\n', file, f_name);
-    try_fwrite(delim, strlen(delim), 1, file, f_name);
+    try_fwrite(world.delim, strlen(world.delim), 1, file, f_name);
 }
 
 
 }
 
 
index 97da5f1628e69e846af57c7edebbf5840997b55c..4ac01d0ebfd6133eabd0aa7047a736c5de30775e 100644 (file)
@@ -37,6 +37,7 @@ struct WinDB
     WINDOW * v_screen; /* virtual screen (ncurses pad) */
     struct Win * wins; /* array of windows */
     struct yx_uint16 v_screen_size; /* virtual screen size */
     WINDOW * v_screen; /* virtual screen (ncurses pad) */
     struct Win * wins; /* array of windows */
     struct yx_uint16 v_screen_size; /* virtual screen size */
+    char * legal_ids; /* ids allowed to be used */
     char * ids; /* all windows' ids, followed by \0 */
     char * order; /* visible windows' id's order, followed by \0 */
     uint16_t v_screen_offset; /* how many cells v_screen view moved rightwards*/
     char * ids; /* all windows' ids, followed by \0 */
     char * order; /* visible windows' id's order, followed by \0 */
     uint16_t v_screen_offset; /* how many cells v_screen view moved rightwards*/
@@ -71,19 +72,25 @@ extern uint16_t center_offset(uint16_t position,
 extern struct Win * get_win_by_id(char id);
 
 /* Read/write individual Win (identified by "c") and world.winDB.order /
 extern struct Win * get_win_by_id(char id);
 
 /* Read/write individual Win (identified by "c") and world.winDB.order /
- * world.winDB.active from/to "file". Follow writing with "delim" delimiter.
- * Use "line" and "linemax" as expected by try_fgets().
+ * world.winDB.active from/to "file" up to the world.delim delimiter. Use "line"
+ * and "linemax" as expected by try_fgets().
  *
  * Note that read_winconf_from_file() returns 1 on success and 0 if it detects
  * having found the end of the valid interface configuration file by either
  * hitting a EOF or a newline (so empty newlines at the end of the file are ok).
  *
  * Note that read_winconf_from_file() returns 1 on success and 0 if it detects
  * having found the end of the valid interface configuration file by either
  * hitting a EOF or a newline (so empty newlines at the end of the file are ok).
+ *
+ * Note that read_order_wins_visible_active() only reads the promised values
+ * into pointers for temporary storage. This is due to the order in which window
+ * data is initialized: winDB.order and winDB.active should only be set when all
+ * windows have been initialized, so cleaning up on error is not confused.
  */
 extern uint8_t read_winconf_from_file(char * line, uint32_t linemax,
                                       FILE * file);
  */
 extern uint8_t read_winconf_from_file(char * line, uint32_t linemax,
                                       FILE * file);
-extern void write_winconf_of_id_to_file(FILE * file, char c, char * delim);
+extern void write_winconf_of_id_to_file(FILE * file, char c);
 extern void read_order_wins_visible_active(char * line, uint32_t linemax,
 extern void read_order_wins_visible_active(char * line, uint32_t linemax,
-                                           FILE * file);
-extern void write_order_wins_visible_active(FILE * file, char * delim);
+                                           FILE * file, char ** tmp_order,
+                                           char * tmp_active);
+extern void write_order_wins_visible_active(FILE * file);
 
 /* Builds virtual sreen from .t_screen's size, fits win's sizes to them.*/
 extern void make_v_screen_and_init_win_sizes();
 
 /* Builds virtual sreen from .t_screen's size, fits win's sizes to them.*/
 extern void make_v_screen_and_init_win_sizes();
index a71f772db401b0d7ea5b5adfd432ac5b97c42308..307f53f92d11098786cb58cd09071b505e1de1aa 100644 (file)
@@ -28,9 +28,10 @@ struct World
     struct yx_uint16 player_pos; /* coordinates of player on map */
     char * log; /* log of player's activities */
     char * path_server_in; /* path of server's input fifo */
     struct yx_uint16 player_pos; /* coordinates of player on map */
     char * log; /* log of player's activities */
     char * path_server_in; /* path of server's input fifo */
-    char * path_interface_conf; /* path of interface configuration file */
+    char * path_interface; /* path of interface configuration file */
     char * path_commands; /* path of commands config file */
     char * player_inventory; /* one-item-per-line string list of owned items */
     char * path_commands; /* path of commands config file */
     char * player_inventory; /* one-item-per-line string list of owned items */
+    char * delim; /* delimiter for multi-line blocks in config files */
     uint16_t turn; /* world/game turn */
     uint16_t player_score; /* player's score*/
     uint8_t halfdelay; /* how long to wait for getch() input in io_loop() */
     uint16_t turn; /* world/game turn */
     uint16_t player_score; /* player's score*/
     uint8_t halfdelay; /* how long to wait for getch() input in io_loop() */