Project Homepage Sourceforge Page CVS Repository Freshmeat.net Page Download project Author's Homepage

main.c

Go to the documentation of this file.
00001 /*! \file main.c
00002   \brief run-free main file
00003 
00004   run-free is a command line launching program written in gtk. This
00005   version of run-free is written is C for gtk+1.2
00006 */
00007 
00008 /*! \mainpage 
00009  * \htmlinclude mainpage.html
00010  * 
00011  * \htmlinclude maingraph.html
00012  * 
00013  * <b>Here is the README file for this project:</b>
00014  * \verbinclude README
00015  *
00016  * <b>Please note the License for this project:</b>
00017  * \verbinclude COPYING
00018  */
00019 
00020 /* NOTICE:
00021     Copyright (C) 2004  Karl N. Redman (SleepingStill.com)
00022 
00023     This program is free software; you can redistribute it and/or modify
00024     it under the terms of the GNU General Public License as published by
00025     the Free Software Foundation; either version 2 of the License, or
00026     (at your option) any later version.
00027 
00028     This program is distributed in the hope that it will be useful,
00029     but WITHOUT ANY WARRANTY; without even the implied warranty of
00030     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00031     GNU General Public License for more details.
00032 
00033     You should have received a copy of the GNU General Public License
00034     along with this program; if not, write to the Free Software
00035     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00036 
00037     For further information contact: parasyte@sleepingstill.com
00038 */
00039 
00040 
00041 #ifdef HAVE_CONFIG_H
00042 #  include <config.h>
00043 #endif
00044 
00045 
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <string.h>
00049 #include <gtk/gtk.h>
00050 
00051 #include "interface.h"
00052 #include "support.h"
00053 #include "main.h"
00054 #include "comboBox.h"
00055 #include "kbhit.h"
00056 #include "commonDefs.h"
00057 #include "debug.h"
00058 #include "comboHandlers.h"
00059 #include "help.h"
00060 
00061 #include <getopt.h>
00062 /** @name getopt externs
00063  *  externs from getopt functionality
00064  */
00065 //@{ 
00066 ///command line options
00067 extern char *optarg;                    
00068 ///option arguments
00069 extern int optind, opterr, optopt;
00070 ///the environment
00071 extern char **environ;                  
00072 //@}
00073 
00074 /// The Main
00075 /** Long mian function that is intended to be split up some day
00076  */
00077 int
00078 main (int argc, char *argv[], char *env[])
00079 {
00080   gboolean gui =TRUE, history_set =FALSE, listops = FALSE;
00081   
00082 
00083   int opt =0;
00084 
00085 
00086   /*Global_Initialization -Items initialized for runtime
00087    */
00088   history_file = NULL;          
00089   command = NULL;
00090   terminal_path = NULL;
00091   die = TRUE;                   
00092   run_in_term = FALSE;          
00093   no_kbhit = FALSE;
00094   combo_mode = RF_HISTORY_MODE; 
00095   keep_open = FALSE;
00096 
00097   //init gtk stuff
00098   gtk_set_locale ();
00099   gtk_init (&argc, &argv);
00100 
00101   char *home_directory = getenv("HOME"); /*! get the user's home directory */
00102 
00103   //show debug mode message
00104   dprint("run-free: debug mode enabled");
00105 
00106   //loop through the argument options
00107   while(1)
00108     {
00109       int option_index = 0;
00110       static struct option long_options[] = {
00111         {"bash", 0, 0, 'b'},
00112         {"command", 1, 0, 'c'},
00113         {"die", 0, 0, 'd'},
00114         {"help", 0, 0, 'h'},
00115         {"histlen", 1, 0, 0},
00116         {"history", 1, 0, 0},
00117         {"kbhit", 0, 0, 'k'},
00118         {"nokbhit", 0, 0, 'i'},
00119         {"keystrokes", 0, 0, 'y'},
00120         {"listops", 0, 0, 'l'},
00121         {"termstay", 0, 0, 'o'},
00122         {"runterm", 0, 0, 'r'},
00123         {"terminal", 1, 0, 't'},
00124         {"version", 0, 0, 'V'},
00125         //{"smart", 0, 0, 's'},
00126         {0, 0, 0, 0}
00127       };
00128 
00129       /**\todo cleanup getopt stuff -it's messy! */
00130 
00131       //do command line processing
00132       opt = getopt_long(argc, argv, "bc:dhiklort:yV", long_options, &option_index);
00133 
00134       if(opt == -1)
00135         break;
00136       
00137       switch(opt)
00138         {
00139         case 0:         //long arguments
00140           if(strcmp(long_options[option_index].name, OPTARG_HISTORY) ==0)
00141             {
00142               //handle history file
00143               if(strcmp(optarg, OPTARG_HISTORY_FILETYPE_RF)==0) //run-free
00144                 {
00145                   history_file = g_malloc(strlen(home_directory)+strlen(RF_HISTORY_FILENAME)+2);
00146                   sprintf(history_file, "%s/%s", home_directory, RF_HISTORY_FILENAME);
00147                 }
00148               else if(strcmp(optarg, OPTARG_HISTORY_FILETYPE_BASH)==0) //bash
00149                 {
00150                   history_file = g_malloc(strlen(home_directory)+strlen(BASH_HISTORY_FILENAME)+2);
00151                   sprintf(history_file, "%s/%s", home_directory, BASH_HISTORY_FILENAME);
00152                 }
00153               else
00154                 {
00155                   history_file = g_malloc(strlen(optarg)+1);
00156                   sprintf(history_file,"%s", optarg); //xxx
00157                 }
00158               history_set++;
00159             }
00160           else if(strcmp(long_options[option_index].name, OPTARG_HISTORY_LEN) ==0)
00161             {
00162               history_len = atol(optarg);
00163             }
00164           break;
00165         case 'b':
00166           bash_shell_mode = TRUE;
00167           break;
00168         case 'c':
00169           //copy command from command line
00170           if(optarg)
00171             {
00172               command = g_malloc(strlen(optarg)+1);
00173               sprintf(command, "%s", optarg);           /* copy the string */
00174             }
00175           break;
00176         case 'd':
00177           die = FALSE;
00178           break;
00179         case 'h':
00180           g_print("%s: version %s.\n%s\n", PACKAGE, VERSION, COPYRIGHT);
00181           g_print("%s\n\n", LICENSE);
00182           g_print("\nHELP:\n");
00183           char *help = 
00184             "-b, --bash\t\tRun in Bash mode (reads ~/.bashrc before execution)"
00185             "\n"
00186             "-c, --command=COMMAND\tSet COMMAND in entry box on startup"
00187             "\n"
00188             "-d, --die\t\tDo NOT die after executing a command"
00189             "\n"
00190             "-h, --help\t\tThis help list"
00191             "\n"
00192             "    --histlen=NUM\tShow NUM items from history in history list"
00193             "\n"
00194             "    --history=FILEPATH\tUse history file from FILEPATH"
00195             "\n"
00196             "-i, --nokbhit\t\tDo NOT allow keyboard hit mode (DON'T show \"HIT ANY KEY\" on exit)"
00197             "\n"
00198             "-k, --kbhit\t\tRun in keyboard hit mode (show \"HIT ANY KEY\" and exit)"
00199             "\n"
00200             "-l, --listops\t\tList default (compiled in) options and exit"
00201             "\n"
00202             "-o, --termstay\t\tKeep the terminal open after command exec"
00203             "\n"
00204             "-r, --runterm\t\tSet run_in_term mode on startup"
00205             "\n"
00206             "-t, --terminal=TERMPATH\tUse TERMPATH program for run_in_terminal mode"
00207             "\n"
00208             "-y, --keystrokes\tDisplay the keystrokes for run-free"
00209             "\n"
00210             "-V, --version\t\tShow version and copyright information"
00211             "\n";
00212           g_print("%s", help);
00213           exit(0);
00214           break;
00215         case 'i':
00216           no_kbhit = TRUE;
00217           break;
00218         case 'k':
00219           gui = FALSE;
00220           break;
00221         case 'l':
00222           listops = TRUE;
00223           break;
00224         case 'o':
00225           keep_open = TRUE;
00226           break;
00227         case 'r':
00228           run_in_term = TRUE;
00229           break;
00230         case 't':
00231           if(optarg)
00232             {
00233               terminal_path = g_malloc(strlen(optarg)+1);
00234               sprintf(terminal_path, "%s", optarg);
00235             }
00236           break;
00237         case 'y':
00238           g_print("%s: version %s.\n%s\n", PACKAGE, VERSION, COPYRIGHT);
00239           g_print("%s\n\n", LICENSE);
00240           g_print("\nKEYSTROKES:\n");
00241           g_print("%s\n",KEYSTROKES);
00242 
00243           /**\todo add cleanup routines */
00244 
00245           //cleanup
00246           freeList(cbitems);
00247           g_free(history_file);
00248           g_free(home_directory);
00249           g_free(command);
00250           g_free(terminal_path);
00251           exit(0);
00252           break;
00253         case 'V':
00254           g_print("%s: version %s.\n%s\n", PACKAGE, VERSION, COPYRIGHT);
00255           g_print("%s\n\n", LICENSE);
00256           exit(0);
00257           break;
00258         default:
00259           dprint("an argument is not being delt with");
00260           break;
00261         }
00262     }
00263   
00264 
00265   //handle options not set
00266   if(!history_set)
00267     {
00268       //string terminators are accounted for
00269 #ifdef USE_USER_HISTORY_FILENAME 
00270       dprint_s2("user history compile option",USER_HISTORY_FILENAME);
00271       history_file = g_malloc(strlen(USER_HISTORY_FILENAME)+1);
00272       sprintf(history_file, "%s", USER_HISTORY_FILENAME);
00273 #else 
00274       dprint_s2("bash history compile option",BASH_HISTORY_FILENAME);
00275       history_file = g_malloc(strlen(home_directory)+strlen(BASH_HISTORY_FILENAME)+2);
00276       sprintf(history_file, "%s/%s", home_directory, BASH_HISTORY_FILENAME);
00277 #endif
00278     }
00279 
00280   if(!history_len)
00281     history_len = DEFAULT_HISTORY_LEN;
00282 
00283   if(terminal_path == NULL)
00284     {
00285       terminal_path = g_malloc(strlen(DEFAULT_TERMINAL_PATH)+1);
00286       sprintf(terminal_path, "%s", DEFAULT_TERMINAL_PATH);
00287     }
00288 
00289   if(listops)
00290     {
00291       g_print("%s: version %s.\n%s\n", PACKAGE, VERSION, COPYRIGHT);
00292       g_print("%s\n\n", LICENSE);
00293       g_print("\n");
00294 
00295 #ifdef USE_USER_HISTORY_FILENAME
00296       char *use_user_history_filename = "yes";
00297 #else
00298       char *use_user_history_filename = "no";
00299 #endif
00300       //list the default run-time options and exit
00301       g_print("debug mode \t\t\t\t=%s\n", DEBUG_MODE?"yes":"no");
00302       g_print("default history display length\t\t=%d\n", history_len);
00303       g_print("use user history file by default\t=%s\n",use_user_history_filename);
00304       g_print("name of default user history file: %s\n", USER_HISTORY_FILENAME);
00305       g_print("name of default bash history file:%s/%s\n", home_directory, BASH_HISTORY_FILENAME);
00306       g_print("run_in_term mode terminal path:%s\n", terminal_path);
00307       exit(0);
00308     }
00309 
00310 
00311   //post handle command line options 
00312   if(!gui)
00313     {
00314         do_kbhit();
00315       
00316       //cleanup
00317       freeList(cbitems);
00318       g_free(history_file);
00319       g_free(home_directory);
00320       g_free(command);
00321       g_free(terminal_path);
00322     }
00323   else
00324     {
00325       //already did this
00326       //gtk_set_locale ();
00327       //gtk_init (&argc, &argv);
00328     
00329       //create the main window
00330       mainWindow = create_mainWindow ();
00331       gtk_widget_show (mainWindow);
00332 
00333       //we create it but don't show it until it's needed
00334       fileselection = create_fileselection ();
00335 
00336       //set the state of the run_in_term button
00337       if(run_in_term)
00338         {
00339           run_in_term = FALSE;  /* cheezy */
00340           gtk_button_clicked(GTK_BUTTON(checkbutton)); 
00341         }
00342 
00343       //initialize the combo box in history mode
00344       //combo_init(RF_HISTORY_MODE);
00345       combo_init(RF_EXAMPLE_MODE);
00346       combo_init(RF_HISTORY_MODE);
00347 
00348       if(command !=NULL)
00349         {
00350           //gtk_entry_set_text(combo_entry1, command);
00351           gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo1)->entry), command);
00352           dprint_s2("startup command", command);
00353         }
00354       
00355       //run the program
00356       gtk_main ();
00357     }
00358 
00359   return 0;
00360 }
00361 
00362 
00363 #include <sys/types.h>
00364 #include <unistd.h>
00365 
00366 /** 
00367     \brief Internal custom "system" call
00368 
00369     \author Karl N. Redman
00370 
00371     \param command The command we want to run
00372 
00373     <b>
00374     Purpose:</b> 
00375     Execute the command in a way that is consistant with the
00376     design of run-free.
00377     
00378     \note
00379     This is a custom system() type call in order to handle
00380     environment settings properly (in the future) if this program is
00381     to be a setuid application (which is in the works) 
00382 */
00383 void run_command(char *command)
00384 {
00385 
00386   char pre[64], post[64], *buffer;
00387 
00388   //anything except NULL is allowed.
00389   if(!command)
00390     return;
00391 
00392   //populate parts of the command
00393   if(run_in_term)
00394     {
00395       //we want to run this in a terminal so act accordingly
00396       if(bash_shell_mode == TRUE)
00397         {
00398           //endable user alias settings (i.e. ls --color)
00399           strcpy(pre," -e bash -i -c \'");
00400         }
00401       else
00402         {
00403           strcpy(pre," -e sh -c \'");
00404         }
00405 
00406       if(!no_kbhit)
00407         {
00408           //alsways show "HIT ANY KEY"
00409           if(keep_open)
00410             if(bash_shell_mode == TRUE)
00411               strcpy(post, ";  bash -i \'&");
00412             else
00413               strcpy(post, ";  sh \'&");
00414           else
00415             strcpy(post, "; run-free -k \'&");
00416         }
00417       else
00418         if(keep_open)
00419             if(bash_shell_mode == TRUE)
00420               strcpy(post, ";  bash -i \'&");
00421             else
00422               strcpy(post, ";  sh \'&");
00423         else
00424           strcpy(post, "; \'&");
00425         
00426 
00427       //allocate a buffer
00428       buffer = g_malloc(strlen(terminal_path)
00429                       +strlen(pre)
00430                       +strlen(command)
00431                       +strlen(post)
00432                       +1);
00433       
00434       //populate the buffer with the command
00435       sprintf(buffer, "%s%s%s%s", terminal_path, pre, command, post);
00436     }
00437   else
00438     {
00439       //no terminal, we must want to just execute something in the
00440       //background
00441       strcpy(pre, "");
00442       strcpy(post, " &");
00443 
00444       //allocate a buffer
00445       buffer = g_malloc( +strlen(pre)
00446                       +strlen(command)
00447                       +strlen(post)
00448                       +1);
00449       
00450       //populate the buffer with the command
00451       sprintf(buffer, "%s%s%s", pre, command, post);
00452     }
00453       
00454 
00455 
00456   //fork the program to execute the command
00457   int pid = fork();
00458 
00459   //if we are the child...
00460   if(pid == 0)
00461     {
00462       //update the history file
00463       writeHistory(command, history_file);
00464 
00465       //populate the command to execute 
00466       char * argv[4];
00467       argv[0] = "sh";
00468       argv[1] = "-c";
00469       argv[2] = (char *)buffer;
00470       argv[3] = 0;
00471 
00472       /**\warning
00473          NOTE: this function is a potential security problem because we are not
00474          replacing the environment. if this is ever going to be a SUID
00475          application then I need to handle this. I'll work on this in the
00476          future -parasyte
00477       */
00478       //execute the program
00479       execve("/bin/sh", argv, environ);
00480       
00481       //free memory
00482       g_free(buffer);
00483 
00484       //exit properly
00485       exit(0);
00486     }
00487   else
00488     {
00489       g_free(buffer);
00490 
00491       if(die)
00492         {
00493           //kill the main program
00494           gtk_main_quit();
00495         }
00496       else
00497         {
00498           //update the history list
00499           combo_init(combo_mode);
00500         }
00501     }
00502 }
00503 

Generated on Thu Mar 18 07:26:17 2004 for run-free by doxygen 1.3.5