+static char *run_notify;
+static char *default_name = "Tea";
+static int expired;
+static int notify_pid = 0;
+static gint notify_watch = 0;
+static int kill_notify_by = 0;
+
+static void
+kill_notify(void)
+{
+ if (kill_notify_by && notify_pid)
+ {
+ kill(notify_pid, kill_notify_by);
+ notify_pid = 0;
+ }
+ if (notify_watch)
+ {
+ g_source_remove(notify_watch);
+ notify_watch = 0;
+ }
+}
+
+static void
+quit(void)
+{
+ kill_notify();
+ gtk_main_quit();
+}
+
+static int // return pid of new process or 0 if failed
+expand_and_exec(char *cmd)
+{
+ GError *err = NULL;
+ gint argc;
+ gchar ** argv = NULL;
+ int pid;
+
+ g_shell_parse_argv(cmd, &argc, &argv, &err);
+ GString ** expanded_argv = malloc(sizeof(expanded_argv[0])*argc);
+ if (!expanded_argv)
+ return 0;
+ gchar ** expanded_argv_gchar = malloc(sizeof(expanded_argv_gchar[0])*(argc+1));
+ if (err)
+ {
+ fprintf(stderr, "teatimer: Unable to parse command: %s\n", err->message);
+ g_error_free(err);
+ return 0;
+ }
+ if(!expanded_argv_gchar) return 0;
+ for (int i=0; i<argc; i++)
+ {
+ expanded_argv[i] = g_string_new("");
+ for (int j=0; argv[i][j]; j++)
+ {
+ if (argv[i][j]=='%' && argv[i][j+1]=='%')
+ {
+ j++;
+ g_string_append_c(expanded_argv[i], '%');
+ }
+ else
+ if (argv[i][j]=='%' && argv[i][j+1]=='n')
+ {
+ j++;
+ const gchar * name = gtk_entry_get_text(GTK_ENTRY(namebox));
+ g_string_append(expanded_argv[i], name);
+ }
+ else
+ g_string_append_c(expanded_argv[i], argv[i][j]);
+ }
+ expanded_argv_gchar[i] = expanded_argv[i]->str;
+ }
+ expanded_argv_gchar[argc]=NULL;
+ g_spawn_async(NULL, expanded_argv_gchar, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &pid, &err);
+ g_strfreev(argv);
+ for (int i=0; i<argc; i++)
+ g_string_free(expanded_argv[i], 1);
+ if (err)
+ {
+ fprintf(stderr, "teatimer: Unable to run command: %s\n", err->message);
+ g_error_free(err);
+ return 0;
+ }
+ return pid;
+}
+
+static void
+notify_exit(GPid pid, gint status UNUSED, gpointer data UNUSED)
+{
+ if (notify_pid == pid)
+ notify_pid = 0;
+}