2009-02-25 16:15:16 +03:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/resource.h>
# include <unistd.h>
# include <signal.h>
# include <errno.h>
2009-03-06 15:12:27 +03:00
# include <FL/x.H>
2009-02-25 17:03:00 +03:00
# include <FL/Fl.H>
# include <FL/Fl_Box.H>
# include <FL/Fl_Button.H>
2009-02-25 17:42:40 +03:00
# include <FL/Fl_Check_Button.H>
2009-02-25 17:03:00 +03:00
# include <FL/Fl_Input.H>
# include <FL/Fl_Pixmap.H>
2009-02-25 16:15:16 +03:00
# include <edelib/Run.h>
2009-02-25 17:03:00 +03:00
# include <edelib/Window.h>
# include <edelib/Nls.h>
2009-02-27 17:37:09 +03:00
# include <edelib/Debug.h>
2009-03-06 15:12:27 +03:00
# include <edelib/Missing.h>
2009-02-27 17:37:09 +03:00
# include <edelib/MessageBox.h>
2009-03-06 15:12:27 +03:00
2009-02-25 17:03:00 +03:00
# include "icons/run.xpm"
/*
* Window from X11 is alread included with Fl . H so we can ' t use
* EDELIB_NS_USING ( Window ) here . Stupid C + + namespaces
*/
# define LaunchWindow edelib::Window
2009-02-25 16:15:16 +03:00
2009-02-27 17:37:09 +03:00
EDELIB_NS_USING ( run_sync )
2009-03-06 15:12:27 +03:00
EDELIB_NS_USING ( run_async )
2009-02-27 17:37:09 +03:00
EDELIB_NS_USING ( alert )
2009-02-25 16:15:16 +03:00
2009-03-30 19:17:00 +04:00
static Fl_Pixmap image_run ( ( const char * * ) run_xpm ) ;
2009-02-25 17:42:40 +03:00
static Fl_Input * dialog_input ;
static Fl_Check_Button * in_term ;
2009-02-25 16:15:16 +03:00
void help ( void ) {
puts ( " Usage: ede-launch [OPTIONS] program " ) ;
puts ( " EDE program launcher " ) ;
}
static char * * cmd_split ( const char * cmd ) {
int sz = 10 ;
int i = 0 ;
char * c = strdup ( cmd ) ;
char * * arr = ( char * * ) malloc ( sizeof ( char * ) * sz ) ;
for ( char * p = strtok ( c , " " ) ; p ; p = strtok ( NULL , " " ) ) {
if ( i > = sz ) {
sz * = 2 ;
arr = ( char * * ) realloc ( arr , sizeof ( char * ) * sz ) ;
}
arr [ i + + ] = strdup ( p ) ;
}
arr [ i ] = NULL ;
free ( c ) ;
return arr ;
}
static void start_crasher ( const char * cmd , int sig ) {
/*
* call edelib implementation instead start_child_process ( )
* to prevents loops if ' ede - crasher ' crashes
*/
2009-02-27 17:37:09 +03:00
run_sync ( " ede-crasher --apppath %s --signal %i " , cmd , sig ) ;
2009-02-25 16:15:16 +03:00
}
static int start_child_process ( const char * cmd ) {
int pid , in [ 2 ] , out [ 2 ] , err [ 2 ] ;
char * * params = cmd_split ( cmd ) ;
pipe ( in ) ;
pipe ( out ) ;
pipe ( err ) ;
signal ( SIGCHLD , SIG_DFL ) ;
pid = fork ( ) ;
switch ( pid ) {
case 0 :
/* child process */
close ( 0 ) ;
dup ( in [ 0 ] ) ;
close ( in [ 0 ] ) ;
close ( in [ 1 ] ) ;
close ( 1 ) ;
dup ( out [ 1 ] ) ;
close ( out [ 0 ] ) ;
close ( out [ 1 ] ) ;
close ( 2 ) ;
dup ( err [ 1 ] ) ;
close ( err [ 0 ] ) ;
close ( err [ 1 ] ) ;
errno = 0 ;
/* start it */
execvp ( params [ 0 ] , params ) ;
2009-02-27 17:37:09 +03:00
/* some programs use value 2 (tar) */
2009-02-25 16:15:16 +03:00
if ( errno = = 2 )
_exit ( 199 ) ;
else
_exit ( errno ) ;
break ;
case - 1 :
2009-02-27 17:37:09 +03:00
E_WARNING ( E_STRLOC " : fork() failed \n " ) ;
2009-02-25 16:15:16 +03:00
/* close the pipes */
close ( in [ 0 ] ) ;
close ( in [ 1 ] ) ;
close ( out [ 0 ] ) ;
close ( out [ 1 ] ) ;
close ( err [ 0 ] ) ;
close ( err [ 1 ] ) ;
break ;
default :
/* perent */
close ( in [ 0 ] ) ;
close ( out [ 1 ] ) ;
close ( err [ 1 ] ) ;
break ;
}
2009-02-27 17:37:09 +03:00
int status , ret ;
errno = 0 ;
2009-02-25 16:15:16 +03:00
if ( waitpid ( pid , & status , 0 ) < 0 ) {
2009-02-27 17:37:09 +03:00
E_WARNING ( E_STRLOC " : waitpid() failed with '%s' \n " , strerror ( errno ) ) ;
2009-02-25 16:15:16 +03:00
return 1 ;
}
if ( WIFEXITED ( status ) ) {
2009-02-27 17:37:09 +03:00
ret = WEXITSTATUS ( status ) ;
2009-02-25 16:15:16 +03:00
} else if ( WIFSIGNALED ( status ) & & WTERMSIG ( status ) = = SIGSEGV ) {
start_crasher ( cmd , SIGSEGV ) ;
} else {
2009-02-27 17:37:09 +03:00
E_WARNING ( E_STRLOC " : child '%s' killed \n " , cmd ) ;
2009-02-25 16:15:16 +03:00
}
2009-02-27 17:37:09 +03:00
return ret ;
2009-02-25 16:15:16 +03:00
}
2009-02-27 17:37:09 +03:00
static int start_child_process_with_core ( const char * cmd ) {
2009-02-25 16:15:16 +03:00
struct rlimit r ;
2009-02-27 17:37:09 +03:00
errno = 0 ;
2009-02-25 17:03:00 +03:00
if ( getrlimit ( RLIMIT_CORE , & r ) = = - 1 ) {
2009-02-27 17:37:09 +03:00
E_WARNING ( E_STRLOC " : gerlimit() failed with '%s' \n " , strerror ( errno ) ) ;
return - 1 ;
2009-02-25 17:03:00 +03:00
}
2009-02-25 16:15:16 +03:00
rlim_t old = r . rlim_cur ;
r . rlim_cur = RLIM_INFINITY ;
2009-02-25 17:03:00 +03:00
if ( setrlimit ( RLIMIT_CORE , & r ) = = - 1 ) {
2009-02-27 17:37:09 +03:00
E_WARNING ( E_STRLOC " : setrlimit() failed with '%s' \n " , strerror ( errno ) ) ;
return - 1 ;
2009-02-25 17:03:00 +03:00
}
2009-02-25 16:15:16 +03:00
2009-02-27 17:37:09 +03:00
int ret = start_child_process ( cmd ) ;
2009-02-25 16:15:16 +03:00
r . rlim_cur = old ;
2009-02-25 17:03:00 +03:00
if ( setrlimit ( RLIMIT_CORE , & r ) = = - 1 ) {
2009-02-27 17:37:09 +03:00
E_WARNING ( E_STRLOC " : setrlimit() failed with '%s' \n " , strerror ( errno ) ) ;
return - 1 ;
2009-02-25 17:03:00 +03:00
}
2009-02-27 17:37:09 +03:00
return ret ;
2009-02-25 17:03:00 +03:00
}
2009-02-25 16:15:16 +03:00
2009-03-05 21:21:37 +03:00
static bool start_child ( const char * cmd ) {
2009-03-06 15:12:27 +03:00
run_async ( " ede-launch-sn --program %s --icon applications-order " , cmd ) ;
2009-03-05 21:21:37 +03:00
int ret = start_child_process_with_core ( cmd ) ;
if ( ret = = 199 ) {
2009-03-06 15:12:27 +03:00
alert ( _ ( " Program '%s' not found. \n \n Please check if given path to the executable was correct or adjust $PATH environment variable to point to the directory where target executable exists " ) , cmd ) ;
2009-03-05 21:21:37 +03:00
return false ;
}
if ( ret = = EACCES ) {
2009-03-06 15:12:27 +03:00
/* now check the if file is executable since EACCES is common error if not so */
if ( access ( cmd , X_OK ) ! = 0 )
alert ( _ ( " You are trying to execute '%s', but it is not executable file " ) , cmd ) ;
else
alert ( _ ( " You do not have enough permissions to execute '%s' " ) , cmd ) ;
2009-03-05 21:21:37 +03:00
return false ;
}
return true ;
}
2009-02-25 17:03:00 +03:00
static void cancel_cb ( Fl_Widget * , void * w ) {
LaunchWindow * win = ( LaunchWindow * ) w ;
win - > hide ( ) ;
}
static void ok_cb ( Fl_Widget * , void * w ) {
LaunchWindow * win = ( LaunchWindow * ) w ;
const char * cmd = dialog_input - > value ( ) ;
2009-03-05 21:21:37 +03:00
bool started = false ;
2009-02-27 17:37:09 +03:00
2009-02-25 17:03:00 +03:00
win - > hide ( ) ;
/* do not block dialog when program is starting */
Fl : : check ( ) ;
2009-02-25 17:42:40 +03:00
/* TODO: is 'cmd' safe after hide? */
if ( in_term - > value ( ) ) {
2009-03-06 15:12:27 +03:00
char buf [ 128 ] ;
2009-02-25 17:42:40 +03:00
char * term = getenv ( " TERM " ) ;
if ( ! term )
term = " xterm " ;
2009-03-06 15:12:27 +03:00
snprintf ( buf , sizeof ( buf ) , " %s -e %s " , term , cmd ) ;
started = start_child ( buf ) ;
2009-02-25 17:42:40 +03:00
} else {
2009-03-05 21:21:37 +03:00
started = start_child ( cmd ) ;
2009-02-27 17:37:09 +03:00
}
2009-03-05 21:21:37 +03:00
if ( ! started ) {
2009-02-27 17:37:09 +03:00
/* show dialog again */
win - > show ( ) ;
2009-02-25 17:42:40 +03:00
}
2009-02-25 17:03:00 +03:00
}
static void start_dialog ( int argc , char * * argv ) {
2009-02-25 17:42:40 +03:00
LaunchWindow * win = new LaunchWindow ( 370 , 195 , _ ( " Run Command " ) ) ;
2009-02-25 17:03:00 +03:00
win - > begin ( ) ;
Fl_Box * icon = new Fl_Box ( 10 , 10 , 55 , 55 ) ;
icon - > image ( image_run ) ;
Fl_Box * txt = new Fl_Box ( 70 , 10 , 290 , 69 , _ ( " Enter the name of the application you would like to run or the URL you would like to view " ) ) ;
txt - > align ( 132 | FL_ALIGN_INSIDE ) ;
dialog_input = new Fl_Input ( 70 , 90 , 290 , 25 , _ ( " Open: " ) ) ;
2009-02-25 17:42:40 +03:00
in_term = new Fl_Check_Button ( 70 , 125 , 290 , 25 , _ ( " Run in terminal " ) ) ;
in_term - > down_box ( FL_DOWN_BOX ) ;
Fl_Button * ok = new Fl_Button ( 175 , 160 , 90 , 25 , _ ( " &OK " ) ) ;
2009-02-25 17:03:00 +03:00
ok - > callback ( ok_cb , win ) ;
2009-02-25 17:42:40 +03:00
Fl_Button * cancel = new Fl_Button ( 270 , 160 , 90 , 25 , _ ( " &Cancel " ) ) ;
2009-02-25 17:03:00 +03:00
cancel - > callback ( cancel_cb , win ) ;
win - > end ( ) ;
win - > show ( argc , argv ) ;
while ( win - > shown ( ) )
Fl : : wait ( ) ;
2009-02-25 16:15:16 +03:00
}
int main ( int argc , char * * argv ) {
2009-02-25 17:03:00 +03:00
if ( argc = = 1 )
start_dialog ( argc , argv ) ;
else if ( argc ! = 2 ) {
2009-02-25 16:15:16 +03:00
help ( ) ;
return 0 ;
2009-02-25 17:03:00 +03:00
} else {
2009-03-05 21:21:37 +03:00
start_child ( argv [ 1 ] ) ;
2009-02-25 16:15:16 +03:00
}
2009-02-27 17:37:09 +03:00
return 0 ;
2009-02-25 16:15:16 +03:00
}