+static gboolean menu_pipe_submenu(gpointer key, gpointer val, gpointer data)
+{
+ ObMenu *menu = val;
+ return menu->pipe_creator == data;
+}
+
+void menu_pipe_execute(ObMenu *self)
+{
+ xmlDocPtr doc;
+ xmlNodePtr node;
+ gchar *output;
+ GError *err = NULL;
+
+ if (!self->execute)
+ return;
+
+ if (!g_spawn_command_line_sync(self->execute, &output, NULL, NULL, &err)) {
+ g_warning("Failed to execute command for pipe-menu: %s", err->message);
+ g_error_free(err);
+ return;
+ }
+
+ if (parse_load_mem(output, strlen(output),
+ "openbox_pipe_menu", &doc, &node))
+ {
+ g_hash_table_foreach_remove(menu_hash, menu_pipe_submenu, self);
+ menu_clear_entries(self);
+
+ menu_parse_state.pipe_creator = self;
+ menu_parse_state.parent = self;
+ parse_tree(menu_parse_inst, doc, node->children);
+ xmlFreeDoc(doc);
+ } else {
+ g_warning("Invalid output from pipe-menu: %s", self->execute);
+ }
+
+ g_free(output);
+}
+