From c88c3e3ab2c16da734f0897701c51faf3df84768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Tarl=C3=A1=20Cardoso=20Lemos?= Date: Wed, 1 Dec 2010 00:14:08 -0200 Subject: [PATCH] Default to a file in /tmp for the restart state. The file is now created in /tmp using the process PID and the username of the user running i3. The restart state file is only loaded when restarting (the --restart option is appended to the command line prior to the restart). That means that renaming the old state file with the ".old" extension is no longer needed. This "--restart" switch is supposed to be only used by i3. The "-L" switch can be used to load a layout (and not delete it afterwards). We unlink the state file after we load it so that we don't keep cruft in /tmp or try to restart from an old config file if restart_state is set. --- include/tree.h | 2 +- src/config.c | 1 - src/main.c | 25 ++++++++++++++-- src/tree.c | 13 ++------- src/util.c | 78 ++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 95 insertions(+), 24 deletions(-) diff --git a/include/tree.h b/include/tree.h index f04e9e62..6376ed92 100644 --- a/include/tree.h +++ b/include/tree.h @@ -82,6 +82,6 @@ void tree_close(Con *con, bool kill_window, bool dont_kill_parent); * Loads tree from ~/.i3/_restart.json (used for in-place restarts). * */ -bool tree_restore(); +bool tree_restore(const char *path); #endif diff --git a/src/config.c b/src/config.c index 683310c8..8a394c1f 100644 --- a/src/config.c +++ b/src/config.c @@ -323,7 +323,6 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath, INIT_COLOR(config.bar.unfocused, "#333333", "#222222", "#888888"); INIT_COLOR(config.bar.urgent, "#2f343a", "#900000", "#ffffff"); - config.restart_state_path = "~/.i3/_restart.json"; config.default_border = BS_NORMAL; parse_configuration(override_configpath); diff --git a/src/main.c b/src/main.c index 121100b5..b6923d6a 100644 --- a/src/main.c +++ b/src/main.c @@ -76,6 +76,8 @@ int main(int argc, char *argv[]) { int screens; char *override_configpath = NULL; bool autostart = true; + char *layout_path = NULL; + bool delete_layout_path; bool only_check_config = false; bool force_xinerama = false; xcb_intern_atom_cookie_t atom_cookies[NUM_ATOMS]; @@ -84,6 +86,8 @@ int main(int argc, char *argv[]) { {"config", required_argument, 0, 'c'}, {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, + {"layout", required_argument, 0, 'L'}, + {"restart", required_argument, 0, 0}, {"force-xinerama", no_argument, 0, 0}, {0, 0, 0, 0} }; @@ -97,12 +101,16 @@ int main(int argc, char *argv[]) { start_argv = argv; - while ((opt = getopt_long(argc, argv, "c:Cvahld:V", long_options, &option_index)) != -1) { + while ((opt = getopt_long(argc, argv, "c:CvaL:hld:V", long_options, &option_index)) != -1) { switch (opt) { case 'a': LOG("Autostart disabled using -a\n"); autostart = false; break; + case 'L': + layout_path = sstrdup(optarg); + delete_layout_path = false; + break; case 'c': override_configpath = sstrdup(optarg); break; @@ -132,12 +140,17 @@ int main(int argc, char *argv[]) { "Please check if your driver really does not support RandR " "and disable this option as soon as you can.\n"); break; + } else if (strcmp(long_options[option_index].name, "restart") == 0) { + layout_path = sstrdup(optarg); + delete_layout_path = true; + break; } /* fall-through */ default: fprintf(stderr, "Usage: %s [-c configfile] [-d loglevel] [-a] [-v] [-V] [-C]\n", argv[0]); fprintf(stderr, "\n"); fprintf(stderr, "-a: disable autostart\n"); + fprintf(stderr, "-L : load the layout from \n"); fprintf(stderr, "-v: display version and exit\n"); fprintf(stderr, "-V: enable verbose mode\n"); fprintf(stderr, "-d : enable debug loglevel \n"); @@ -327,7 +340,15 @@ int main(int argc, char *argv[]) { #endif } - if (!tree_restore()) + bool needs_tree_init = true; + if (layout_path) { + LOG("Trying to restore the layout from %s...", layout_path); + needs_tree_init = !tree_restore(layout_path); + if (delete_layout_path) + unlink(layout_path); + free(layout_path); + } + if (needs_tree_init) tree_init(); tree_render(); diff --git a/src/tree.c b/src/tree.c index f1b521e8..1edbf735 100644 --- a/src/tree.c +++ b/src/tree.c @@ -13,8 +13,8 @@ struct all_cons_head all_cons = TAILQ_HEAD_INITIALIZER(all_cons); * Loads tree from ~/.i3/_restart.json (used for in-place restarts). * */ -bool tree_restore() { - char *globbed = resolve_tilde(config.restart_state_path); +bool tree_restore(const char *path) { + char *globbed = resolve_tilde(path); if (!path_exists(globbed)) { LOG("%s does not exist, not restoring tree\n", globbed); @@ -28,15 +28,6 @@ bool tree_restore() { tree_append_json(globbed); - size_t path_len = strlen(config.restart_state_path); - char *old_restart = smalloc(path_len + strlen(".old") + 1); - strncpy(old_restart, config.restart_state_path, path_len + strlen(".old") + 1); - strncat(old_restart, ".old", strlen(".old") + 1); - unlink(old_restart); - rename(globbed, old_restart); - free(globbed); - free(old_restart); - printf("appended tree, using new root\n"); croot = TAILQ_FIRST(&(croot->nodes_head)); printf("new root = %p\n", croot); diff --git a/src/util.c b/src/util.c index 89f55960..b8c314c7 100644 --- a/src/util.c +++ b/src/util.c @@ -16,8 +16,8 @@ #if defined(__OpenBSD__) #include #endif - #include +#include #include "all.h" @@ -238,10 +238,29 @@ static char **append_argument(char **original, char *argument) { return result; } +/* + * Returns the name of a temporary file with the specified prefix. + * + */ +char *get_process_filename(const char *prefix) +{ + struct passwd *pw = getpwuid(getuid()); + const char *username = pw ? pw->pw_name : "unknown"; + char *filename; + int res = asprintf(&filename, "/tmp/%s-%s.%d", prefix, username, getpid()); + if (res == -1) { + perror("asprintf()"); + return NULL; + } + else { + return filename; + } +} + #define y(x, ...) yajl_gen_ ## x (gen, ##__VA_ARGS__) #define ystr(str) yajl_gen_string(gen, (unsigned char*)str, strlen(str)) -void store_restart_layout() { +char *store_restart_layout() { setlocale(LC_NUMERIC, "C"); yajl_gen gen = yajl_gen_alloc(NULL, NULL); @@ -253,12 +272,22 @@ void store_restart_layout() { unsigned int length; y(get_buf, &payload, &length); - char *globbed = resolve_tilde(config.restart_state_path); - int fd = open(globbed, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); - free(globbed); + /* create a temporary file if one hasn't been specified, or just + * resolve the tildes in the specified path */ + char *filename; + if (config.restart_state_path == NULL) { + filename = get_process_filename("i3-restart-state"); + if (!filename) + return NULL; + } else { + filename = resolve_tilde(config.restart_state_path); + } + + int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd == -1) { perror("open()"); - return; + free(filename); + return NULL; } int written = 0; @@ -267,11 +296,13 @@ void store_restart_layout() { /* TODO: correct error-handling */ if (n == -1) { perror("write()"); - return; + free(filename); + return NULL; } if (n == 0) { printf("write == 0?\n"); - return; + free(filename); + return NULL; } written += n; printf("written: %d of %d\n", written, length); @@ -281,6 +312,8 @@ void store_restart_layout() { printf("layout: %.*s\n", length, payload); y(free); + + return filename; } /* @@ -289,7 +322,7 @@ void store_restart_layout() { * */ void i3_restart() { - store_restart_layout(); + char *restart_filename = store_restart_layout(); restore_geometry(); ipc_shutdown(); @@ -298,6 +331,33 @@ void i3_restart() { /* make sure -a is in the argument list or append it */ start_argv = append_argument(start_argv, "-a"); + /* replace -r so that the layout is restored */ + if (restart_filename != NULL) { + /* create the new argv */ + int num_args; + for (num_args = 0; start_argv[num_args] != NULL; num_args++); + char **new_argv = scalloc((num_args + 3) * sizeof(char*)); + + /* copy the arguments, but skip the ones we'll replace */ + int write_index = 0; + bool skip_next = false; + for (int i = 0; i < num_args; ++i) { + if (skip_next) + skip_next = false; + else if (!strcmp(start_argv[i], "-r")) + skip_next = true; + else + new_argv[write_index++] = start_argv[i]; + } + + /* add the arguments we'll replace */ + new_argv[write_index++] = "--restart"; + new_argv[write_index++] = restart_filename; + + /* swap the argvs */ + start_argv = new_argv; + } + execvp(start_argv[0], start_argv); /* not reached */ }