]> git.sur5r.net Git - i3/i3/blobdiff - src/cfgparse.y
Bugfix: use bufcopy instead of buf when boundary checking (Thanks thomasba)
[i3/i3] / src / cfgparse.y
index f9d4ef35574933b9eed6f63614974d2f292d4c3e..dc29860cda021f1f23552ed0bfce8cfaf25aa2d6 100644 (file)
@@ -8,7 +8,6 @@
 #include <sys/wait.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <limits.h>
 
 #include "all.h"
 
@@ -19,6 +18,7 @@ static Match current_match;
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
 extern int yylex(struct context *context);
 extern int yyparse(void);
+extern int yylex_destroy(void);
 extern FILE *yyin;
 YY_BUFFER_STATE yy_scan_string(const char *);
 
@@ -114,7 +114,7 @@ next:
 }
 
 /*
- * Calls i3-migrate-config-to-v4.pl to migrate a configuration file (input
+ * Calls i3-migrate-config-to-v4 to migrate a configuration file (input
  * buffer).
  *
  * Returns the converted config file or NULL if there was an error (for
@@ -152,7 +152,7 @@ static char *migrate_config(char *input, off_t size) {
             NULL, /* will be replaced by the executable path */
             NULL
         };
-        exec_i3_utility("i3-migrate-config-to-v4.pl", argv);
+        exec_i3_utility("i3-migrate-config-to-v4", argv);
     }
 
     /* parent */
@@ -188,6 +188,7 @@ static char *migrate_config(char *input, off_t size) {
         ret = read(readpipe[0], converted + read_bytes, conv_size - read_bytes);
         if (ret == -1) {
             warn("Cannot read from pipe");
+            FREE(converted);
             return NULL;
         }
         read_bytes += ret;
@@ -350,13 +351,20 @@ void parse_file(const char *f) {
             continue;
 
         if (strcasecmp(key, "set") == 0) {
-            if (value[0] != '$')
-                die("Malformed variable assignment, name has to start with $\n");
+            if (value[0] != '$') {
+                ELOG("Malformed variable assignment, name has to start with $\n");
+                continue;
+            }
 
             /* get key/value for this variable */
             char *v_key = value, *v_value;
-            if ((v_value = strstr(value, " ")) == NULL)
-                die("Malformed variable assignment, need a value\n");
+            if (strstr(value, " ") == NULL && strstr(value, "\t") == NULL) {
+                ELOG("Malformed variable assignment, need a value\n");
+                continue;
+            }
+
+            if (!(v_value = strstr(value, " ")))
+                v_value = strstr(value, "\t");
 
             *(v_value++) = '\0';
 
@@ -369,7 +377,6 @@ void parse_file(const char *f) {
         }
     }
     fclose(fstr);
-    close(fd);
 
     /* For every custom variable, see how often it occurs in the file and
      * how much extra bytes it requires when replaced. */
@@ -383,7 +390,8 @@ void parse_file(const char *f) {
         int extra = (strlen(current->value) - strlen(current->key));
         char *next;
         for (next = bufcopy;
-             (next = strcasestr(bufcopy + (next - bufcopy), current->key)) != NULL;
+             next < (bufcopy + stbuf.st_size) &&
+             (next = strcasestr(next, current->key)) != NULL;
              next += strlen(current->key)) {
             *next = '_';
             extra_bytes += extra;
@@ -438,7 +446,7 @@ void parse_file(const char *f) {
             printf("\n");
             printf("Please convert your config file to v4. You can use this command:\n");
             printf("    mv %s %s.O\n", f, f);
-            printf("    i3-migrate-config-to-v4.pl %s.O > %s\n", f, f);
+            printf("    i3-migrate-config-to-v4 %s.O > %s\n", f, f);
             printf("****************************************************************\n");
             printf("\n");
             free(new);
@@ -446,7 +454,7 @@ void parse_file(const char *f) {
         } else {
             printf("\n");
             printf("**********************************************************************\n");
-            printf("ERROR: Could not convert config file. Maybe i3-migrate-config-to-v4.pl\n");
+            printf("ERROR: Could not convert config file. Maybe i3-migrate-config-to-v4\n");
             printf("was not correctly installed on your system?\n");
             printf("**********************************************************************\n");
             printf("\n");
@@ -468,6 +476,7 @@ void parse_file(const char *f) {
         start_configerror_nagbar(f);
     }
 
+    yylex_destroy();
     FREE(context->line_copy);
     free(context);
     free(new);
@@ -547,6 +556,7 @@ void parse_file(const char *f) {
 
 %token              TOK_MARK            "mark"
 %token              TOK_CLASS           "class"
+%token              TOK_INSTANCE        "instance"
 %token              TOK_ID              "id"
 %token              TOK_CON_ID          "con_id"
 %token              TOK_TITLE           "title"
@@ -652,6 +662,10 @@ bindsym:
 for_window:
     TOK_FOR_WINDOW match command
     {
+        if (match_is_empty(&current_match)) {
+            ELOG("Match is empty, ignoring this for_window statement\n");
+            break;
+        }
         printf("\t should execute command %s for the criteria mentioned above\n", $3);
         Assignment *assignment = scalloc(sizeof(Assignment));
         assignment->type = A_COMMAND;
@@ -684,11 +698,21 @@ matchend:
     ;
 
 criteria:
+    criteria criterion
+    | criterion
+    ;
+
+criterion:
     TOK_CLASS '=' STR
     {
         printf("criteria: class = %s\n", $3);
         current_match.class = $3;
     }
+    | TOK_INSTANCE '=' STR
+    {
+        printf("criteria: instance = %s\n", $3);
+        current_match.instance = $3;
+    }
     | TOK_CON_ID '=' STR
     {
         printf("criteria: id = %s\n", $3);
@@ -925,10 +949,25 @@ workspace:
             }
 
             DLOG("Should assign workspace %s to output %s\n", ws_name, $4);
-            struct Workspace_Assignment *assignment = scalloc(sizeof(struct Workspace_Assignment));
-            assignment->name = ws_name;
-            assignment->output = $4;
-            TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments);
+            /* Check for earlier assignments of the same workspace so that we
+             * don’t have assignments of a single workspace to different
+             * outputs */
+            struct Workspace_Assignment *assignment;
+            bool duplicate = false;
+            TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+                if (strcasecmp(assignment->name, ws_name) == 0) {
+                    ELOG("You have a duplicate workspace assignment for workspace \"%s\"\n",
+                         ws_name);
+                    assignment->output = $4;
+                    duplicate = true;
+                }
+            }
+            if (!duplicate) {
+                assignment = scalloc(sizeof(struct Workspace_Assignment));
+                assignment->name = ws_name;
+                assignment->output = $4;
+                TAILQ_INSERT_TAIL(&ws_assignments, assignment, ws_assignments);
+            }
         }
     }
     | TOKWORKSPACE NUMBER workspace_name
@@ -985,7 +1024,7 @@ assign:
         /* Compatibility with older versions: If the assignment target starts
          * with ~, we create the equivalent of:
          *
-         * for_window [class="foo"] mode floating
+         * for_window [class="foo"] floating enable
          */
         if (*workspace == '~') {
             workspace++;
@@ -1061,6 +1100,7 @@ font:
     {
         config.font = load_font($2, true);
         printf("font %s\n", $2);
+        free($2);
     }
     ;
 
@@ -1089,6 +1129,7 @@ colorpixel:
         char *hex;
         if (asprintf(&hex, "#%s", $2) == -1)
             die("asprintf()");
+        free($2);
         $$ = get_colorpixel(hex);
         free(hex);
     }