X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Futil.c;h=57bfa89bb77051a53a5964ee4c3f7520079391ff;hb=fb90a556c88027b2ba639037bacb55770414a4e2;hp=a72b52d5073d720c44ba3590bc7805baf48b0725;hpb=8a40dc0011828f57661a6bd9e2df09c138f4a1a9;p=i3%2Fi3 diff --git a/src/util.c b/src/util.c index a72b52d5..57bfa89b 100644 --- a/src/util.c +++ b/src/util.c @@ -2,26 +2,26 @@ * vim:ts=4:sw=4:expandtab * * i3 - an improved dynamic tiling window manager + * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) * - * © 2009-2010 Michael Stapelberg and contributors - * - * See file LICENSE for license information. - * - * util.c: Utility functions, which can be useful everywhere. + * util.c: Utility functions, which can be useful everywhere within i3 (see + * also libi3). * */ +#include "all.h" + #include #include -#include #if defined(__OpenBSD__) #include #endif #include #include +#include +#include -#include "all.h" - -static iconv_t conversion_descriptor = 0; +#define SN_API_NOT_YET_FROZEN 1 +#include int min(int a, int b) { return (a < b ? a : b); @@ -57,64 +57,50 @@ bool update_if_necessary(uint32_t *destination, const uint32_t new_value) { } /* - * The s* functions (safe) are wrappers around malloc, strdup, …, which exits if one of - * the called functions returns NULL, meaning that there is no more memory available + * exec()s an i3 utility, for example the config file migration script or + * i3-nagbar. This function first searches $PATH for the given utility named, + * then falls back to the dirname() of the i3 executable path and then falls + * back to the dirname() of the target of /proc/self/exe (on linux). * - */ -void *smalloc(size_t size) { - void *result = malloc(size); - exit_if_null(result, "Error: out of memory (malloc(%zd))\n", size); - return result; -} - -void *scalloc(size_t size) { - void *result = calloc(size, 1); - exit_if_null(result, "Error: out of memory (calloc(%zd))\n", size); - return result; -} - -void *srealloc(void *ptr, size_t size) { - void *result = realloc(ptr, size); - exit_if_null(result, "Error: out memory (realloc(%zd))\n", size); - return result; -} - -char *sstrdup(const char *str) { - char *result = strdup(str); - exit_if_null(result, "Error: out of memory (strdup())\n"); - return result; -} - -/* - * Starts the given application by passing it through a shell. We use double fork - * to avoid zombie processes. As the started application’s parent exits (immediately), - * the application is reparented to init (process-id 1), which correctly handles - * childs, so we don’t have to do it :-). + * This function should be called after fork()ing. + * + * The first argument of the given argv vector will be overwritten with the + * executable name, so pass NULL. * - * The shell is determined by looking for the SHELL environment variable. If it - * does not exist, /bin/sh is used. + * If the utility cannot be found in any of these locations, it exits with + * return code 2. * */ -void start_application(const char *command) { - LOG("executing: %s\n", command); - if (fork() == 0) { - /* Child process */ - setsid(); - if (fork() == 0) { - /* Stores the path of the shell */ - static const char *shell = NULL; - - if (shell == NULL) - if ((shell = getenv("SHELL")) == NULL) - shell = "/bin/sh"; - - /* This is the child */ - execl(shell, shell, "-c", command, (void*)NULL); - /* not reached */ - } - exit(0); +void exec_i3_utility(char *name, char *argv[]) { + /* start the migration script, search PATH first */ + char *migratepath = name; + argv[0] = migratepath; + execvp(migratepath, argv); + + /* if the script is not in path, maybe the user installed to a strange + * location and runs the i3 binary with an absolute path. We use + * argv[0]’s dirname */ + char *pathbuf = strdup(start_argv[0]); + char *dir = dirname(pathbuf); + sasprintf(&migratepath, "%s/%s", dir, name); + argv[0] = migratepath; + execvp(migratepath, argv); + +#if defined(__linux__) + /* on linux, we have one more fall-back: dirname(/proc/self/exe) */ + char buffer[BUFSIZ]; + if (readlink("/proc/self/exe", buffer, BUFSIZ) == -1) { + warn("could not read /proc/self/exe"); + exit(1); } - wait(0); + dir = dirname(buffer); + sasprintf(&migratepath, "%s/%s", dir, name); + argv[0] = migratepath; + execvp(migratepath, argv); +#endif + + warn("Could not start %s", name); + exit(2); } /* @@ -131,50 +117,6 @@ void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_mes } } -/* - * Converts the given string to UCS-2 big endian for use with - * xcb_image_text_16(). The amount of real glyphs is stored in real_strlen, - * a buffer containing the UCS-2 encoded string (16 bit per glyph) is - * returned. It has to be freed when done. - * - */ -char *convert_utf8_to_ucs2(char *input, int *real_strlen) { - size_t input_size = strlen(input) + 1; - /* UCS-2 consumes exactly two bytes for each glyph */ - int buffer_size = input_size * 2; - - char *buffer = smalloc(buffer_size); - size_t output_size = buffer_size; - /* We need to use an additional pointer, because iconv() modifies it */ - char *output = buffer; - - /* We convert the input into UCS-2 big endian */ - if (conversion_descriptor == 0) { - conversion_descriptor = iconv_open("UCS-2BE", "UTF-8"); - if (conversion_descriptor == 0) { - fprintf(stderr, "error opening the conversion context\n"); - exit(1); - } - } - - /* Get the conversion descriptor back to original state */ - iconv(conversion_descriptor, NULL, NULL, NULL, NULL); - - /* Convert our text */ - int rc = iconv(conversion_descriptor, (void*)&input, &input_size, &output, &output_size); - if (rc == (size_t)-1) { - perror("Converting to UCS-2 failed"); - if (real_strlen != NULL) - *real_strlen = 0; - return NULL; - } - - if (real_strlen != NULL) - *real_strlen = ((buffer_size - output_size) / 2) - 1; - - return buffer; -} - /* * This function resolves ~ in pathnames. * It may resolve wildcards in the first part of the path, but if no match @@ -248,16 +190,10 @@ char *get_process_filename(const char *prefix) { if (dir == NULL) { struct passwd *pw = getpwuid(getuid()); const char *username = pw ? pw->pw_name : "unknown"; - if (asprintf(&dir, "/tmp/i3-%s", username) == -1) { - perror("asprintf()"); - return NULL; - } + sasprintf(&dir, "/tmp/i3-%s", username); } else { char *tmp; - if (asprintf(&tmp, "%s/i3", dir) == -1) { - perror("asprintf()"); - return NULL; - } + sasprintf(&tmp, "%s/i3", dir); dir = tmp; } if (!path_exists(dir)) { @@ -267,11 +203,7 @@ char *get_process_filename(const char *prefix) { } } char *filename; - if (asprintf(&filename, "%s/%s.%d", dir, prefix, getpid()) == -1) { - perror("asprintf()"); - filename = NULL; - } - + sasprintf(&filename, "%s/%s.%d", dir, prefix, getpid()); free(dir); return filename; } @@ -281,14 +213,22 @@ char *get_process_filename(const char *prefix) { char *store_restart_layout() { setlocale(LC_NUMERIC, "C"); +#if YAJL_MAJOR >= 2 + yajl_gen gen = yajl_gen_alloc(NULL); +#else yajl_gen gen = yajl_gen_alloc(NULL, NULL); +#endif dump_node(gen, croot, true); setlocale(LC_NUMERIC, ""); const unsigned char *payload; +#if YAJL_MAJOR >= 2 + size_t length; +#else unsigned int length; +#endif y(get_buf, &payload, &length); /* create a temporary file if one hasn't been specified, or just @@ -316,19 +256,27 @@ char *store_restart_layout() { if (n == -1) { perror("write()"); free(filename); + close(fd); return NULL; } if (n == 0) { printf("write == 0?\n"); free(filename); + close(fd); return NULL; } written += n; +#if YAJL_MAJOR >= 2 + printf("written: %d of %zd\n", written, length); +#else printf("written: %d of %d\n", written, length); +#endif } close(fd); - printf("layout: %.*s\n", length, payload); + if (length > 0) { + printf("layout: %.*s\n", (int)length, payload); + } y(free); @@ -343,6 +291,8 @@ char *store_restart_layout() { void i3_restart(bool forget_layout) { char *restart_filename = forget_layout ? NULL : store_restart_layout(); + kill_configerror_nagbar(true); + restore_geometry(); ipc_shutdown(); @@ -364,7 +314,8 @@ void i3_restart(bool forget_layout) { for (int i = 0; i < num_args; ++i) { if (skip_next) skip_next = false; - else if (!strcmp(start_argv[i], "-r")) + else if (!strcmp(start_argv[i], "-r") || + !strcmp(start_argv[i], "--restart")) skip_next = true; else new_argv[write_index++] = start_argv[i]; @@ -382,9 +333,7 @@ void i3_restart(bool forget_layout) { /* not reached */ } -#if 0 - -#if defined(__OpenBSD__) +#if defined(__OpenBSD__) || defined(__APPLE__) /* * Taken from FreeBSD @@ -392,31 +341,30 @@ void i3_restart(bool forget_layout) { * */ void *memmem(const void *l, size_t l_len, const void *s, size_t s_len) { - register char *cur, *last; - const char *cl = (const char *)l; - const char *cs = (const char *)s; + register char *cur, *last; + const char *cl = (const char *)l; + const char *cs = (const char *)s; - /* we need something to compare */ - if (l_len == 0 || s_len == 0) - return NULL; + /* we need something to compare */ + if (l_len == 0 || s_len == 0) + return NULL; - /* "s" must be smaller or equal to "l" */ - if (l_len < s_len) - return NULL; + /* "s" must be smaller or equal to "l" */ + if (l_len < s_len) + return NULL; - /* special case where s_len == 1 */ - if (s_len == 1) - return memchr(l, (int)*cs, l_len); + /* special case where s_len == 1 */ + if (s_len == 1) + return memchr(l, (int)*cs, l_len); - /* the last position where its possible to find "s" in "l" */ - last = (char *)cl + l_len - s_len; + /* the last position where its possible to find "s" in "l" */ + last = (char *)cl + l_len - s_len; - for (cur = (char *)cl; cur <= last; cur++) - if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) - return cur; + for (cur = (char *)cl; cur <= last; cur++) + if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) + return cur; - return NULL; + return NULL; } #endif -#endif