X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=i3-nagbar%2Fmain.c;h=a9619f9620913c9bcc0920343adb9946199358ef;hb=78e99440f6ff144bb6842f3fb33c1f65faadc4df;hp=e700e2e9259a299564cd7208a6470807d613c4ef;hpb=fc0e80ee7f94c74a6b9097299870c80f18c8bfe7;p=i3%2Fi3 diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c index e700e2e9..a9619f96 100644 --- a/i3-nagbar/main.c +++ b/i3-nagbar/main.c @@ -2,7 +2,7 @@ * vim:ts=4:sw=4:expandtab * * i3 - an improved dynamic tiling window manager - * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) + * © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE) * * i3-nagbar is a utility which displays a nag message, for example in the case * when the user has an error in his configuration file. @@ -30,6 +30,8 @@ #include "libi3.h" #include "i3-nagbar.h" +static char *argv0 = NULL; + typedef struct { i3String *label; char *action; @@ -148,7 +150,7 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve * */ char *script_path = get_process_filename("nagbar-cmd"); - int fd = open(script_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR); + int fd = open(script_path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd == -1) { warn("Could not create temporary script to store the nagbar command"); return; @@ -162,11 +164,18 @@ static void handle_button_release(xcb_connection_t *conn, xcb_button_release_eve /* Also closes fd */ fclose(script); + char *link_path; + sasprintf(&link_path, "%s.nagbar_cmd", script_path); + symlink(get_exe_path(argv0), link_path); + char *terminal_cmd; - sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", script_path); + sasprintf(&terminal_cmd, "i3-sensible-terminal -e %s", link_path); + printf("argv0 = %s\n", argv0); + printf("terminal_cmd = %s\n", terminal_cmd); start_application(terminal_cmd); + free(link_path); free(terminal_cmd); free(script_path); @@ -269,6 +278,41 @@ static int handle_expose(xcb_connection_t *conn, xcb_expose_event_t *event) { } int main(int argc, char *argv[]) { + /* The following lines are a terribly horrible kludge. Because terminal + * emulators have different ways of interpreting the -e command line + * argument (some need -e "less /etc/fstab", others need -e less + * /etc/fstab), we need to write commands to a script and then just run + * that script. However, since on some machines, $XDG_RUNTIME_DIR and + * $TMPDIR are mounted with noexec, we cannot directly execute the script + * either. + * + * Initially, we tried to pass the command via the environment variable + * _I3_NAGBAR_CMD. But turns out that some terminal emulators such as + * xfce4-terminal run all windows from a single master process and only + * pass on the command (not the environment) to that master process. + * + * Therefore, we symlink i3-nagbar (which MUST reside on an executable + * filesystem) with a special name and run that symlink. When i3-nagbar + * recognizes it’s started as a binary ending in .nagbar_cmd, it strips off + * the .nagbar_cmd suffix and runs /bin/sh on argv[0]. That way, we can run + * a shell script on a noexec filesystem. + * + * From a security point of view, i3-nagbar is just an alias to /bin/sh in + * certain circumstances. This should not open any new security issues, I + * hope. */ + char *cmd = NULL; + const size_t argv0_len = strlen(argv[0]); + if (argv0_len > strlen(".nagbar_cmd") && + strcmp(argv[0] + argv0_len - strlen(".nagbar_cmd"), ".nagbar_cmd") == 0) { + unlink(argv[0]); + cmd = strdup(argv[0]); + *(cmd + argv0_len - strlen(".nagbar_cmd")) = '\0'; + execl("/bin/sh", "/bin/sh", cmd, NULL); + err(EXIT_FAILURE, "execv(/bin/sh, /bin/sh, %s)", cmd); + } + + argv0 = argv[0]; + char *pattern = sstrdup("-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"); int o, option_index = 0; enum { TYPE_ERROR = 0, TYPE_WARNING = 1 } bar_type = TYPE_ERROR; @@ -278,7 +322,7 @@ int main(int argc, char *argv[]) { {"font", required_argument, 0, 'f'}, {"button", required_argument, 0, 'b'}, {"help", no_argument, 0, 'h'}, - {"message", no_argument, 0, 'm'}, + {"message", required_argument, 0, 'm'}, {"type", required_argument, 0, 't'}, {0, 0, 0, 0} };