Allow a command to be automatically started when ready

This commit is contained in:
Pierre Pronchery 2013-11-30 10:20:33 +01:00
parent 3a7377408f
commit 044486cf91
3 changed files with 96 additions and 63 deletions

View File

@ -44,7 +44,8 @@
/* private */
/* prototypes */
static int _simulator(char const * model, char const * title);
static int _simulator(char const * model, char const * title,
char const * command);
static int _simulator_list(void);
static int _error(char const * message, int ret);
@ -53,11 +54,12 @@ static int _usage(void);
/* functions */
/* simulator */
static int _simulator(char const * model, char const * title)
static int _simulator(char const * model, char const * title,
char const * command)
{
Simulator * simulator;
if((simulator = simulator_new(model, title)) == NULL)
if((simulator = simulator_new(model, title, command)) == NULL)
return error_print(PROGNAME);
gtk_main();
simulator_delete(simulator);
@ -113,7 +115,7 @@ static int _error(char const * message, int ret)
/* usage */
static int _usage(void)
{
fputs(_("Usage: " PROGNAME " [-m model][-t title]\n"
fputs(_("Usage: " PROGNAME " [-m model][-t title] [command]\n"
" " PROGNAME " -l\n"), stderr);
return 1;
}
@ -128,6 +130,7 @@ int main(int argc, char * argv[])
int list = 0;
char const * model = NULL;
char const * title = NULL;
char const * command = NULL;
if(setlocale(LC_ALL, "") == NULL)
_error("setlocale", 1);
@ -149,9 +152,11 @@ int main(int argc, char * argv[])
default:
return _usage();
}
if(optind != argc)
if(optind + 1 == argc)
command = argv[optind];
else if(optind != argc)
return _usage();
if(list != 0)
return (_simulator_list() == 0) ? 0 : 2;
return (_simulator(model, title) == 0) ? 0 : 2;
return (_simulator(model, title, command) == 0) ? 0 : 2;
}

View File

@ -59,6 +59,7 @@ struct _Simulator
{
char * model;
char * title;
char * command;
int dpi;
int width;
@ -86,6 +87,7 @@ static char const * _authors[] =
static void _simulator_on_child_watch(GPid pid, gint status, gpointer data);
static void _simulator_on_close(gpointer data);
static gboolean _simulator_on_closex(gpointer data);
static void _simulator_on_plug_added(gpointer data);
static void _simulator_on_file_quit(gpointer data);
static void _simulator_on_file_run(gpointer data);
@ -133,7 +135,8 @@ static int _new_load(Simulator * simulator);
/* callbacks */
static gboolean _new_xephyr(gpointer data);
Simulator * simulator_new(char const * model, char const * title)
Simulator * simulator_new(char const * model, char const * title,
char const * command)
{
Simulator * simulator;
GtkAccelGroup * group;
@ -145,12 +148,14 @@ Simulator * simulator_new(char const * model, char const * title)
return NULL;
simulator->model = (model != NULL) ? strdup(model) : NULL;
simulator->title = (title != NULL) ? strdup(title) : NULL;
simulator->command = (command != NULL) ? strdup(command) : NULL;
simulator->pid = -1;
simulator->source = 0;
simulator->window = NULL;
/* check for errors */
if((model != NULL && simulator->model == NULL)
|| (title != NULL && simulator->title == NULL))
|| (title != NULL && simulator->title == NULL)
|| (command != NULL && simulator->command == NULL))
{
simulator_delete(simulator);
return NULL;
@ -191,6 +196,8 @@ Simulator * simulator_new(char const * model, char const * title)
gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, TRUE, 0);
/* view */
simulator->socket = gtk_socket_new();
g_signal_connect_swapped(simulator->socket, "plug-added", G_CALLBACK(
_simulator_on_plug_added), simulator);
gtk_box_pack_start(GTK_BOX(vbox), simulator->socket, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(simulator->window), vbox);
gtk_widget_show_all(simulator->window);
@ -285,6 +292,8 @@ void simulator_delete(Simulator * simulator)
}
if(simulator->window != NULL)
gtk_widget_destroy(simulator->window);
free(simulator->command);
free(simulator->title);
free(simulator->model);
object_delete(simulator);
}
@ -320,6 +329,57 @@ static int _error_text(char const * message, int ret)
}
/* simulator_run */
int simulator_run(Simulator * simulator, char const * command)
{
char const display[] = "DISPLAY=";
char const display1[] = "DISPLAY=:1.0"; /* XXX may be wrong */
char * argv[] = { "/bin/sh", "run", "-c", NULL, NULL };
char ** envp = NULL;
size_t i;
char ** p;
GSpawnFlags flags = G_SPAWN_FILE_AND_ARGV_ZERO | G_SPAWN_SEARCH_PATH;
GError * error = NULL;
/* prepare the arguments */
if((argv[3] = strdup(command)) == NULL)
return -simulator_error(simulator, strerror(errno), 1);
/* prepare the environment */
for(i = 0; environ[i] != NULL; i++)
{
if((p = realloc(envp, sizeof(*p) * (i + 2))) == NULL)
break;
envp = p;
envp[i + 1] = NULL;
if(strncmp(environ[i], display, sizeof(display) - 1) == 0)
envp[i] = strdup(display1);
else
envp[i] = strdup(environ[i]);
if(envp[i] == NULL)
break;
}
if(environ[i] != NULL)
{
for(i = 0; envp[i] != NULL; i++)
free(envp[i]);
free(envp);
free(argv[3]);
return -simulator_error(simulator, strerror(errno), 1);
}
if(g_spawn_async(NULL, argv, envp, flags, NULL, NULL, NULL,
&error) == FALSE)
{
simulator_error(simulator, error->message, 1);
g_error_free(error);
}
for(i = 0; envp[i] != NULL; i++)
free(envp[i]);
free(envp);
free(argv[3]);
return 0;
}
/* private */
/* functions */
/* callbacks */
@ -383,8 +443,6 @@ static void _run_on_choose_response(GtkWidget * widget, gint arg1,
static void _simulator_on_file_run(gpointer data)
{
char const display[] = "DISPLAY=";
char const display1[] = "DISPLAY=:1.0"; /* XXX may be wrong */
Simulator * simulator = data;
GtkWidget * dialog;
GtkWidget * vbox;
@ -392,14 +450,8 @@ static void _simulator_on_file_run(gpointer data)
GtkWidget * entry;
GtkWidget * widget;
GtkFileFilter * filter;
char const * command;
int res;
char * argv[] = { "/bin/sh", "run", "-c", NULL, NULL };
char ** envp = NULL;
size_t i;
char ** p;
GSpawnFlags flags = G_SPAWN_FILE_AND_ARGV_ZERO | G_SPAWN_SEARCH_PATH;
GError * error = NULL;
char const * command;
dialog = gtk_dialog_new_with_buttons("Run...",
GTK_WINDOW(simulator->window),
@ -416,16 +468,20 @@ static void _simulator_on_file_run(gpointer data)
#endif
hbox = gtk_hbox_new(FALSE, 4);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
/* label */
widget = gtk_label_new("Command:");
gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
/* entry */
entry = gtk_entry_new();
gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
/* file chooser */
widget = gtk_file_chooser_dialog_new("Run program...",
GTK_WINDOW(dialog),
GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN,
GTK_RESPONSE_ACCEPT, NULL);
/* file chooser: file filters */
filter = gtk_file_filter_new();
gtk_file_filter_set_name(filter, "Executable files");
gtk_file_filter_add_mime_type(filter, "application/x-executable");
@ -452,55 +508,14 @@ static void _simulator_on_file_run(gpointer data)
widget = gtk_file_chooser_button_new_with_dialog(widget);
gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);
gtk_widget_show_all(vbox);
/* run the dialog */
res = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_hide(dialog);
if(res != GTK_RESPONSE_ACCEPT)
if(res == GTK_RESPONSE_ACCEPT)
{
gtk_widget_destroy(dialog);
return;
}
/* prepare the arguments */
command = gtk_entry_get_text(GTK_ENTRY(entry));
if((argv[3] = strdup(command)) == NULL)
{
simulator_error(simulator, strerror(errno), 1);
gtk_widget_destroy(dialog);
return;
simulator_run(simulator, command);
}
/* prepare the environment */
for(i = 0; environ[i] != NULL; i++)
{
if((p = realloc(envp, sizeof(*p) * (i + 2))) == NULL)
break;
envp = p;
envp[i + 1] = NULL;
if(strncmp(environ[i], display, sizeof(display) - 1) == 0)
envp[i] = strdup(display1);
else
envp[i] = strdup(environ[i]);
if(envp[i] == NULL)
break;
}
if(environ[i] != NULL)
{
for(i = 0; envp[i] != NULL; i++)
free(envp[i]);
free(envp);
free(argv[3]);
simulator_error(simulator, strerror(errno), 1);
gtk_widget_destroy(dialog);
return;
}
if(g_spawn_async(NULL, argv, envp, flags, NULL, NULL, NULL,
&error) == FALSE)
{
simulator_error(simulator, error->message, 1);
g_error_free(error);
}
for(i = 0; envp[i] != NULL; i++)
free(envp[i]);
free(envp);
free(argv[3]);
gtk_widget_destroy(dialog);
}
@ -544,3 +559,13 @@ static void _simulator_on_help_contents(gpointer data)
{
desktop_help_contents(PACKAGE, PROGNAME);
}
/* simulator_on_plug_added */
static void _simulator_on_plug_added(gpointer data)
{
Simulator * simulator = data;
if(simulator->command != NULL)
simulator_run(simulator, simulator->command);
}

View File

@ -28,10 +28,13 @@ typedef struct _Simulator Simulator;
/* public */
/* functions */
/* essential */
Simulator * simulator_new(char const * model, char const * title);
Simulator * simulator_new(char const * model, char const * title,
char const * command);
void simulator_delete(Simulator * simulator);
/* useful */
int simulator_error(Simulator * simulator, char const * message, int ret);
int simulator_run(Simulator * simulator, char const * command);
#endif /* !CODER_SIMULATOR_H */