diff --git a/Makefile b/Makefile
index 29f92d42b153b1beac5d007ed92746a0d7f6f1b4..d33ab82b01038995fffeb2c3ab4f7fad7bfcea5f 100644
--- a/Makefile
+++ b/Makefile
@@ -24,6 +24,8 @@ osd-alsa: osd-alsa.o util.o client.o
 osdd: display.o
 osdd: osdd-file.o osdd-to-string.o
 osdd: osdd-mqtt.o osdd-to-string.o -lpaho-mqtt3a -lpaho-mqtt3c
+osdd: osdd-exec.o osdd-to-string.o
+osdd: osdd-system.o osdd-to-string.o
 
 
 osdd: LDLIBS+=$(shell pkg-config --libs xft) -lXext -lX11 
diff --git a/osdd-exec.c b/osdd-exec.c
new file mode 100644
index 0000000000000000000000000000000000000000..c793701aeef1500f329f0947b69374a182815e09
--- /dev/null
+++ b/osdd-exec.c
@@ -0,0 +1,106 @@
+/*
+ *	On-screen Display
+ *
+ *	(c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
+ */
+
+#include "osdd-exec.h"
+#include "util.h"
+#include "osdd-to-string.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+
+// *************************  STATE STRUCT **********
+
+struct exec_state
+{
+	//struct osd_to_string_state to_string;
+	bool do_not_insert_msg_to_que;
+	bool no_fork;
+	bool arg_by_line;
+	VECTOR(char *) prefix;
+	struct osd_to_string_state to_string;
+};
+
+// *************************  MAIN FUNCTIONS *******
+
+static
+void exec_write(struct exec_state *state, VECTOR(VECTOR(char)) in)
+{
+	if(!in) return;
+	if(fork()==0)
+	{
+		VECTOR(char *) a = VCLONE(state->prefix);
+		for(int i=0;i<VSIZE(in); i++) VPB(a,in[i]);
+		VPB(a, 0);
+		execvp(a[0], a);
+	}
+	for(int i=0;i<VSIZE(in); i++) VFREE(in[i]);
+	VFREE(in);
+}
+
+INIT_FUNC_USING_TO_STRINGS_VECTOR(exec)
+
+// *************************  NEW ******************
+
+static
+void exec_new_help(FILE * f)
+{
+	fprintf(f,"\
+Module EXEC help:\n\
+\t-opt [ARG0] [ARG1] ...\n\
+On each message execute\n\
+ARG0 ARG1 ... [TIME if -t is set] LINE0 LINE1 ...\n\
+" OSDD_TO_STRINGS_VECTOR_HELP "\
+\n\
+");
+}
+
+static 
+struct osd_abstract exec_new(int argc, char ** argv, Display * nope)
+{
+	(void)nope;
+	argc++;argv--;
+	struct osd_abstract r;
+	static const char short_opts[] = "+" OSDD_TO_STRINGS_VECTOR_SHORTOP;
+	static const struct option long_opts[] = {
+		OSDD_TO_STRINGS_VECTOR_LONGOP
+		{ NULL,		0,			NULL,	0   },
+	};
+	memset(&r,0,sizeof(r));
+	struct exec_state *state = xmalloc(sizeof(*state));
+	memset(state,0,sizeof(state)[0]);
+
+	osd_to_string_state_init(&state->to_string);
+
+	int opt;
+	optind = 0;
+	while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) >= 0)
+	{
+		if(!osd_to_strings_vector_parse_arg(&state->to_string,opt))
+		switch (opt)
+		{
+			default:
+				fprintf(stderr,"Option %c not exist\n\n",opt);
+				exec_new_help(stderr);
+				exit(0);
+		}
+	}
+	for(int ind = optind; ind < argc; ind++)
+	{
+		VPB(state->prefix, argv[ind]);
+	}
+
+	INIT_FUNC_TO_ABSTRACT(r, exec)
+	return r;
+}
+
+// *************************  CREATOR ****************************
+
+CREATE_STANDARD_CREATOR(exec , "EXEC")
diff --git a/osdd-exec.h b/osdd-exec.h
new file mode 100644
index 0000000000000000000000000000000000000000..558dd90ff2e31cc9f7b0954dc8136bc16ba5cf72
--- /dev/null
+++ b/osdd-exec.h
@@ -0,0 +1,9 @@
+/*
+ *	On-screen Display
+ *
+ *	(c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
+ */
+
+#include "osdd-set.h"
+
+struct osd_creator_abstract exec_creator_new(void);
diff --git a/osdd-set.h b/osdd-set.h
index 8460c5dd5f5546222d2868141711530653d57dac..e77cbc490d19c190dddee9f5a99554329bedc0b1 100644
--- a/osdd-set.h
+++ b/osdd-set.h
@@ -103,4 +103,27 @@ void msg_active_outputs(struct osd_set *set, struct msg *msg, char * name, bool
 struct msg* osd_set_new_msg(struct osd_set * set);
 void msg_free(struct msg * msg);
 
+
+#define CREATE_STANDARD_CREATOR(NAME, SNAME) \
+struct osd_creator_abstract NAME ## _creator_new(void) \
+{ \
+  struct osd_creator_abstract r; \
+  memset(&r, 0, sizeof(r)); \
+  r.name = SNAME; \
+  r.help = NAME ## _new_help; \
+  r.new.add_one_osd =  NAME ## _new; \
+  return r; \
+}
+
+#define INIT_FUNC_TO_ABSTRACT(r, NAME) \
+{ \
+	r.context = state; \
+	bool (*arrive)(struct NAME ## _state*, struct osd_line*, int) = NAME ## _arrive; \
+	r.arrive = (bool (*)(void*, struct osd_line*, int)) arrive; \
+	void (*show)(struct NAME ## _state*, struct osd_line*, int) = NAME ## _show; \
+	r.show = (void (*)(void*, struct osd_line*, int)) show; \
+	void (*clear)(struct NAME ## _state*) = NAME ## _clear; \
+	r.clear = (void (*)(void*)) clear; \
+}
+
 #endif
diff --git a/osdd-system.c b/osdd-system.c
new file mode 100644
index 0000000000000000000000000000000000000000..784d65da6c9337c845d63e3341ef18ab976db7ac
--- /dev/null
+++ b/osdd-system.c
@@ -0,0 +1,119 @@
+/*
+ *	On-screen Display
+ *
+ *	(c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
+ */
+
+#include "osdd-system.h"
+#include "util.h"
+#include "osdd-to-string.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+
+// *************************  STATE STRUCT **********
+
+struct system_state
+{
+	struct osd_to_string_state to_string;
+	bool no_fork;
+	char * prefix;
+};
+
+// *************************  MAIN FUNCTIONS *******
+
+static
+void system_write(struct system_state *state, VECTOR(char) in)
+{
+	if(!in) return;
+	if(state->no_fork || fork()==0)
+	{
+		if(state->prefix)
+		{
+			VECTOR(char) out = 0;
+			vprint(&out,"%s%s",state->prefix,in);
+			system(out);
+			VFREE(out);
+		}
+		else
+			system(in);
+		if(!state->no_fork) _exit(0);
+	}
+	VFREE(in);
+}
+
+INIT_FUNC_USING_TO_STRING(system)
+
+
+// *************************  NEW ******************
+
+static
+void system_new_help(FILE * f)
+{
+	fprintf(f,"\
+Module EXEC help:\n\
+\t-opt [PREFIX]\n\
+concatenatin of PREFIX and message will be executed by system(3)\n\
+-F, --no-fork\t\tDo not fork before call system\n\
+" OSDD_TO_STRING_HELP "\
+\n\
+");
+}
+
+static 
+struct osd_abstract system_new(int argc, char ** argv, Display * nope)
+{
+	(void)nope;
+	argc++;argv--;
+	struct osd_abstract r;
+	static const char short_opts[] = "+F" OSDD_TO_STRING_SHORTOP;
+	static const struct option long_opts[] = {
+		{ "no-fork",		no_argument,	NULL,	'F' },
+		OSDD_TO_STRING_LONGOP
+		{ NULL,		0,			NULL,	0   },
+	};
+	memset(&r,0,sizeof(r));
+	struct system_state *state = xmalloc(sizeof(*state));
+	memset(state,0,sizeof(state)[0]);
+
+	osd_to_string_state_init(&state->to_string);
+
+	int opt;
+	optind = 0;
+	while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) >= 0)
+	{
+		if(!osd_to_string_parse_arg(&state->to_string,opt))
+		switch (opt)
+		{
+			case 'F':
+				state->no_fork = 1;
+				break;
+			default:
+				fprintf(stderr,"Option %c not exist\n\n",opt);
+				system_new_help(stderr);
+				exit(0);
+		}
+	}
+	int ind = optind;
+	if(ind < argc)
+		state->prefix = argv[ind++];
+	if(ind != argc)
+	{
+		fprintf(stderr,"Too many arguments\n\n");
+		system_new_help(stderr);
+		exit(0);
+
+	}
+
+	INIT_FUNC_TO_ABSTRACT(r, system)
+	return r;
+}
+
+// *************************  CREATOR ****************************
+
+CREATE_STANDARD_CREATOR(system,"SYSTEM")
diff --git a/osdd-system.h b/osdd-system.h
new file mode 100644
index 0000000000000000000000000000000000000000..141196a367bd913e6852052f674849725486382c
--- /dev/null
+++ b/osdd-system.h
@@ -0,0 +1,9 @@
+/*
+ *	On-screen Display
+ *
+ *	(c) 2020--2021 Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
+ */
+
+#include "osdd-set.h"
+
+struct osd_creator_abstract system_creator_new(void);
diff --git a/osdd-to-string.c b/osdd-to-string.c
index f7f28d5ed5296d219a54198e33a56fe0b4b2083b..63c993f19f372e125dcb0f26a0bc2908c5df1afa 100644
--- a/osdd-to-string.c
+++ b/osdd-to-string.c
@@ -18,7 +18,6 @@
 #include <X11/extensions/render.h>
 #include <X11/Xft/Xft.h>
 
-static
 char * expand_backslash(char * in)
 {
 	char * out = xmalloc(strlen(in)+1);
@@ -89,6 +88,29 @@ colorToRGB(char * name, int *r, int *g, int *b)
 
 
 bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg)
+{
+	if(osd_to_strings_vector_parse_arg(state, arg)) return 1;
+	switch(arg)
+	{
+		case 'l':
+			free(state->line_separator);
+			state->line_separator = expand_backslash(optarg);
+			break;
+		case 'm':
+			free(state->msq_separator);
+			state->msq_separator = expand_backslash(optarg);
+			break;
+		case 'T':
+			free(state->time_separator);
+			state->time_separator = expand_backslash(optarg);
+			break;
+		default:
+			return 0;
+	}
+	return 1;
+}
+
+bool osd_to_strings_vector_parse_arg(struct osd_to_string_state *state, char arg)
 {
 	switch(arg)
 	{
@@ -104,14 +126,6 @@ bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg)
 				exit(0);
 			}
 			break;
-		case 'l':
-			free(state->line_separator);
-			state->line_separator = expand_backslash(optarg);
-			break;
-		case 'm':
-			free(state->msq_separator);
-			state->msq_separator = expand_backslash(optarg);
-			break;
 		case 'r':
 			state->replace_no_text = 1;
 			break;
@@ -124,10 +138,6 @@ bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg)
 						exit(0);
 					}
 			break;
-		case 'T':
-			free(state->time_separator);
-			state->time_separator = expand_backslash(optarg);
-			break;
 		case 'e':
 			if(state->end_of_mes_by) free(state->end_of_mes_by);
 			state->end_of_mes_by = expand_backslash(optarg);
@@ -149,29 +159,32 @@ bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg)
 }
 
 static
-void osd_to_string_time(struct osd_to_string_state *state, VECTOR(char) * out)
+VECTOR(char) osd_to_string_time(struct osd_to_string_state *state)
 {
+	VECTOR(char) out=0;
 	switch(state->time_mode)
 	{
 		case FILE_TIME_NO:
 			break;
 		case FILE_TIME_UNIX:
-			vprint(out,"%lld%s",(long long)time(0),state->time_separator);
+			vprint(&out,"%lld",(long long)time(0));
 			break;
 		case FILE_TIME_ISO:
 			{
 				time_t t = time(NULL);
 				struct tm tm = *localtime(&t);
-				vprint(out,"%04d-%02d-%02d %02d:%02d:%02d%s", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,state->time_separator);
+				vprint(&out,"%04d-%02d-%02d %02d:%02d:%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
 			}
 			break;
 	}
+	return out;
 }
 
-VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
+VECTOR(VECTOR(char)) osd_to_strings_vector(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
 {
-	VECTOR(char) out = NULL;
-	osd_to_string_time(state, &out);
+	VECTOR(VECTOR(char)) out = NULL;
+	VECTOR(char) t = osd_to_string_time(state);
+	if(t) VPB(out,t);
 	for(int i=0;i<num_lines;i++)
 	{
 		struct osd_line * line = lines+i;
@@ -218,15 +231,35 @@ VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line *
 			case FILE_COLOR_NO:
 				break;
 		}
-		vprint(&out,"%s%s%s%s", color, text, end_color,state->line_separator);
+		VECTOR(char) l=0;
+		vprint(&l,"%s%s%s", color, text, end_color);
+		VPB(out,l);
 		VFREE(text);
 
 	}
+	return out;
+}
+
+VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
+{
+	VECTOR(char) out = NULL;
+	VRESERVE(out,256);
+	VECTOR(VECTOR(char)) in = osd_to_strings_vector(state, lines, num_lines);
+	for(int i=0; i<VSIZE(in); i++)
+	{
+		if(i==0 && state->time_mode != FILE_TIME_NO)
+			vprint(&out,"%s%s",in[i],state->time_separator);
+		else
+			vprint(&out,"%s%s",in[i],state->line_separator);
+	}
 	vprint(&out,"%s",state->msq_separator);
+	for(int i=0; i<VSIZE(in); i++)
+		VFREE(in[i]);
+	VFREE(in);
 	return out;
 }
 
-VECTOR(char) osd_to_string_arrivee_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
+VECTOR(char) osd_to_string_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
 {
 	if(!state->on_arrive) return 0;
 	return osd_to_string(state, lines, num_lines);
@@ -236,7 +269,6 @@ VECTOR(char) osd_to_string_show_msg(struct osd_to_string_state *state, struct os
 {
 	if(state->on_arrive) return 0;
 	return osd_to_string(state, lines, num_lines);
-
 }
 
 VECTOR(char) osd_to_string_clear_msg(struct osd_to_string_state *state)
@@ -245,11 +277,43 @@ VECTOR(char) osd_to_string_clear_msg(struct osd_to_string_state *state)
 	if(!state->end_of_mes_by) return 0;
 	VECTOR(char) out=0;
 	if(state->end_of_mes_time) 
-		osd_to_string_time(state, &out);
+	{
+		VECTOR(char) t = osd_to_string_time(state);
+		vprint(&out,"%s",t);
+		VFREE(t);
+	}
 	vprint(&out,"%s",state->end_of_mes_by);
 	return out;
 }
 
+VECTOR(VECTOR(char)) osd_to_strings_vector_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
+{
+	if(!state->on_arrive) return 0;
+	return osd_to_strings_vector(state, lines, num_lines);
+}
+
+VECTOR(VECTOR(char)) osd_to_strings_vector_show_msg(struct osd_to_string_state *state, struct osd_line * lines, int num_lines)
+{
+	if(state->on_arrive) return 0;
+	return osd_to_strings_vector(state, lines, num_lines);
+
+}
+
+VECTOR(VECTOR(char)) osd_to_strings_vector_clear_msg(struct osd_to_string_state *state)
+{
+	if(state->on_arrive) return 0;
+	if(!state->end_of_mes_by) return 0;
+	VECTOR(VECTOR(char)) out=0;
+	if(state->end_of_mes_time) 
+	{
+		VECTOR(char) t = osd_to_string_time(state);
+		VPB(out,t);
+	}
+	VADDSIZE(out,1);
+	vprint(&VLAST(out),"%s",state->end_of_mes_by);
+	return out;
+}
+
 void osd_to_string_state_init(struct osd_to_string_state * state)
 {
 	state->line_separator = expand_backslash("\\n");
diff --git a/osdd-to-string.h b/osdd-to-string.h
index c4adfebc35c6687f0f9bb645bc62b7a3f23b30fd..0d38778c152f430d4c96cc3eca2e174487f567f2 100644
--- a/osdd-to-string.h
+++ b/osdd-to-string.h
@@ -8,19 +8,35 @@
 #include "util.h"
 
 #define OSDD_TO_STRING_LONGOP \
-		{ "color",		required_argument,	NULL,	'c' },\
 		{ "line-separator",		required_argument,	NULL,	'l' },\
 		{ "msq-separator",		required_argument,	NULL,	'm' },\
+		{ "time-separator",		required_argument,	NULL,	'T' },\
+	OSDD_TO_STRINGS_VECTOR_LONGOP
+
+#define OSDD_TO_STRINGS_VECTOR_LONGOP \
+		{ "color",		required_argument,	NULL,	'c' },\
 		{ "replace",		no_argument,	NULL,	'r' },\
 		{ "time",		required_argument,	NULL,	't' },\
-		{ "time-separator",		required_argument,	NULL,	'T' },\
 		{ "end",		required_argument,	NULL,	'e' },\
 		{ "end-time",		no_argument,	NULL,	'E' },\
 		{ "on-arrive",		required_argument,	NULL,	'a' },\
 		{ "on-arrive-do-not-que",		required_argument,	NULL,	'A' },\
 
 #define OSDD_TO_STRING_SHORTOP \
-	"c:l:m:rt:T:e:EaA"
+	"l:m:T:" OSDD_TO_STRINGS_VECTOR_SHORTOP
+
+#define OSDD_TO_STRINGS_VECTOR_SHORTOP \
+	"c:rt:T:e:EaA"
+
+#define OSDD_TO_STRINGS_VECTOR_HELP \
+"-c, --color=<{}>\tSet how to print color of messages {no, rgbDEC, rgbHEX, rgbHEXHASHTAG, term, original}\n" \
+"-r, --replace\t\tReplace not alphabet and number in output to '?'\n"\
+"-t, --time=<{}>\t\tSet how to print actual time {no, unix, iso}\n"\
+"-e, --end-<s>\t\tPrint <s> on end of showing message\n"\
+"-E, --end-time\t\tPrint actual time on end messages (format from -t -T)\n"\
+"-a, --on-arrive\t\tPrint message just when arrive (not compatible with -e -E)\n"\
+"-A, --on-arrive\t\tPrint message just when arrive and do not insert it to message queue\n"\
+"\t\t\t\t(not compatible with -e -E)\n"
 
 #define OSDD_TO_STRING_HELP \
 "-c, --color=<{}>\tSet how to print color of messages {no, rgbDEC, rgbHEX, rgbHEXHASHTAG, term, original}\n" \
@@ -30,7 +46,7 @@
 "-t, --time=<{}>\t\tSet how to print actual time {no, unix, iso}\n"\
 "-T, --time-separator=<s>Separator of time and message text\n"\
 "-e, --end-<s>\t\tPrint <s> on end of showing message\n"\
-"-E, --end-time\t\tWrite actual time to end messages (format from -t -T)\n"\
+"-E, --end-time\t\tPrint actual time on end messages (format from -t -T)\n"\
 "-a, --on-arrive\t\tPrint message just when arrive (not compatible with -e -E)\n"\
 "-A, --on-arrive\t\tPrint message just when arrive and do not insert it to message queue\n"\
 "\t\t\t\t(not compatible with -e -E)\n"
@@ -61,11 +77,59 @@ struct osd_to_string_state
 	bool do_not_insert_msg_to_que;
 };
 
+char * expand_backslash(char * in);
+
+VECTOR(VECTOR(char)) osd_to_strings_vector(struct osd_to_string_state *state, struct osd_line * lines, int num_lines);
 VECTOR(char) osd_to_string(struct osd_to_string_state *state, struct osd_line * lines, int num_lines);
 
-VECTOR(char) osd_to_string_arrivee_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines);
+VECTOR(char) osd_to_string_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines);
 VECTOR(char) osd_to_string_show_msg(struct osd_to_string_state *state, struct osd_line * lines, int num_lines);
 VECTOR(char) osd_to_string_clear_msg(struct osd_to_string_state *state);
 
+VECTOR(VECTOR(char)) osd_to_strings_vector_arrive_msq(struct osd_to_string_state *state, struct osd_line * lines, int num_lines);
+VECTOR(VECTOR(char)) osd_to_strings_vector_show_msg(struct osd_to_string_state *state, struct osd_line * lines, int num_lines);
+VECTOR(VECTOR(char)) osd_to_strings_vector_clear_msg(struct osd_to_string_state *state);
+
 bool osd_to_string_parse_arg(struct osd_to_string_state *state, char arg);
+bool osd_to_strings_vector_parse_arg(struct osd_to_string_state *state, char arg);
 void osd_to_string_state_init(struct osd_to_string_state * state);
+
+#define INIT_FUNC_USING_TO_STRING(NAME) \
+static \
+bool NAME ## _arrive(struct NAME ## _state *state, struct osd_line * lines, int num_lines) \
+{ \
+	NAME ## _write(state,osd_to_string_arrive_msq(&state->to_string, lines, num_lines)); \
+	return state->to_string.do_not_insert_msg_to_que; \
+} \
+ \
+static \
+void NAME ## _show(struct NAME ## _state *state, struct osd_line * lines, int num_lines) \
+{ \
+	NAME ## _write(state,osd_to_string_show_msg(&state->to_string, lines, num_lines)); \
+} \
+ \
+static \
+void NAME ## _clear(struct NAME ## _state *state) \
+{ \
+	NAME ## _write(state,osd_to_string_clear_msg(&state->to_string)); \
+}
+
+#define INIT_FUNC_USING_TO_STRINGS_VECTOR(NAME) \
+static \
+bool NAME ## _arrive(struct NAME ## _state *state, struct osd_line * lines, int num_lines) \
+{ \
+	NAME ## _write(state,osd_to_strings_vector_arrive_msq(&state->to_string, lines, num_lines)); \
+	return state->to_string.do_not_insert_msg_to_que; \
+} \
+ \
+static \
+void NAME ## _show(struct NAME ## _state *state, struct osd_line * lines, int num_lines) \
+{ \
+	NAME ## _write(state,osd_to_strings_vector_show_msg(&state->to_string, lines, num_lines)); \
+} \
+ \
+static \
+void NAME ## _clear(struct NAME ## _state *state) \
+{ \
+	NAME ## _write(state,osd_to_strings_vector_clear_msg(&state->to_string)); \
+}
diff --git a/osdd.c b/osdd.c
index b37d0bc603003db70e2c9ffb1fc02a945fbd62ad..0ffa5f49c2899bd13390e5bd965df9becce8bf02 100644
--- a/osdd.c
+++ b/osdd.c
@@ -14,6 +14,8 @@
 #include <locale.h>
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
+#include <signal.h>
+#include <sys/wait.h>
 
 //#undef DEBUG
 #include "util.h"
@@ -22,6 +24,8 @@
 #include "display.h"
 #include "osdd-file.h"
 #include "osdd-mqtt.h"
+#include "osdd-exec.h"
+#include "osdd-system.h"
 
 
 static struct osd_set osd;
@@ -410,6 +414,14 @@ do_test(void)
 
 /*** Main loop ***/
 
+static
+void sigchld(int a)
+{
+	(void)a;
+	int s;
+	wait(&s);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -417,7 +429,10 @@ main(int argc, char **argv)
   VPB(creator,display_by_outputs_creator_new());
   VPB(creator,file_creator_new());
   VPB(creator,mqtt_creator_new());
+  VPB(creator,exec_creator_new());
+  VPB(creator,system_creator_new());
 
+  signal(SIGCHLD, sigchld);
 
   setlocale(LC_CTYPE, "");
   XInitThreads();
diff --git a/util.c b/util.c
index c1044135bd1db829f7e07ef67916a83e8a68d7d9..327f714abe88c2b9d727833b7714d490043366f5 100644
--- a/util.c
+++ b/util.c
@@ -27,6 +27,10 @@ die(char *fmt, ...)
 void *
 xmalloc(int size)
 {
+  /*if(size > 10000)
+  {
+	  fprintf(stderr,"Try alocate %d bytes of memory :-(",size);
+  }*/
   void *p = malloc(size);
   if (!p)
     die("Failed to allocate %d bytes of memory", size);
@@ -36,6 +40,10 @@ xmalloc(int size)
 void *
 xrealloc(void *ptr, int size)
 {
+  /*if(size > 10000)
+  {
+	  fprintf(stderr,"Try alocate %d bytes of memory :-(",size);
+  }*/
   void *p = realloc(ptr, size);
   if (!p)
     die("Failed to re-allocate %d bytes of memory", size);
@@ -129,12 +137,22 @@ int vmax(void * v)
 
 void vfree(void ** v)
 {
-	if(!v) return;
+	if(!*v) return;
 	struct v *this = (struct v*)*v - 1;
 	free(this);
 	*v = 0;
 }
 
+void * vclone(void * v)
+{
+	if(!v) return 0;
+	struct v *this = (struct v*)v - 1;
+	int l = sizeof(struct v) + this->max;
+	struct v *new = xmalloc(l);
+	memcpy(new,this,l);
+	return new->data;
+}
+
 
 
 int FORMAT_CHECK(printf,2,3) vprint(VECTOR(char) *out , char *fmt, ...)
diff --git a/util.h b/util.h
index 40f0edb6ab9ff8365d3f0eec9983d266e616a484..d03b7a15cf2bad74eda25d19bbf15acdd79387b0 100644
--- a/util.h
+++ b/util.h
@@ -42,16 +42,18 @@ void vreserve(void ** v, int s);
 int vsize(void * v);
 int vmax(void * v);
 void vfree(void ** v);
+void * vclone(void * v);
 
 // Macros for multiple size by size of element
-#define VSETSIZE(v,s) {vsetsize((void **)&(v),sizeof(*(v))*(s));}
-#define VADDSIZE(v,s) {vaddsize((void **)&(v),sizeof(*(v))*(s));}
-#define VRESERVE(v,s) {vreserve((void **)&(v),sizeof(*(v))*(s));}
+#define VSETSIZE(v,s) {vsetsize((void **)&(v),(int)sizeof(*(v))*(s));}
+#define VADDSIZE(v,s) {vaddsize((void **)&(v),(int)sizeof(*(v))*(s));}
+#define VRESERVE(v,s) {vreserve((void **)&(v),(int)sizeof(*(v))*(s));}
 #define VSIZE(v) (vsize(v)/(int)sizeof(*(v)))
 #define VMAX(v) (vmax(v)/(int)sizeof(*(v)))
 #define VLAST(v) ((v)[VSIZE(v)-1])
 #define VPB(v,a) {VADDSIZE(v,1);VLAST(v)=a;}
 #define VFREE(v) vfree((void **)&(v))
+#define VCLONE(v) ((typeof(v)) vclone((void *)(v)))
 #define VECTOR(a) a *