/**
 * egg_desktop_file_parse_exec:
 * @desktop_file: a #EggDesktopFile
 * @documents: a list of document paths or URIs
 * @error: error pointer
 *
 * Parses @desktop_file's Exec key, inserting @documents into it, and
 * returns the result.
 *
 * If @documents contains non-file: URIs and @desktop_file does not
 * accept URIs, those URIs will be ignored. Likewise, if @documents
 * contains more elements than @desktop_file accepts, the extra
 * documents will be ignored.
 *
 * Return value: the parsed Exec string
 **/
char *
egg_desktop_file_parse_exec (EggDesktopFile * desktop_file, GSList * documents,
                             GError ** error)
{
    GSList *translated, *docs;
    char *command;

    docs = translated = translate_document_list (desktop_file, documents);
    command = parse_exec (desktop_file, &docs, error);
    free_document_list (translated);

    return command;
}
int main(int argc, char *argv[], char *envp[]){
  root = NULL;
  history = NULL;
  exit_num = 0;
  size_t buff = BUFFSIZE;
  int bytes_read;
  char * cmd_line;
  cmd_line = (char*)malloc(buff + 1);
  for(;;){
#ifdef PROMPT
    printf("==>");
#endif
    bytes_read = getline(&cmd_line,&buff,stdin);//yeah prompt but stupid trailing newline
    if (bytes_read == -1){return 1;}
    else if(cmd_line[strlen(cmd_line) -1] == '\n'){
      cmd_line[strlen(cmd_line) -1] = '\0';
    }
    history = stack_push(history,cmd_line);
    cmd_line = sub_q(cmd_line);
    exit_num = parse_exec(cmd_line);
  }
  printf("goodbye\n");
  return 1;
}
Beispiel #3
0
static gboolean
egg_desktop_file_launchv (EggDesktopFile *desktop_file,
			  GSList *documents, va_list args,
			  GError **error)
{
  EggDesktopFileLaunchOption option;
  GSList *translated_documents = NULL, *docs = NULL;
  char *command, **argv;
  int argc, i, screen_num;
  gboolean success, current_success;
  GdkDisplay *display;
  char *startup_id;

  GPtrArray   *env = NULL;
  char       **variables = NULL;
  GdkScreen   *screen = NULL;
  int          workspace = -1;
  const char  *directory = NULL;
  guint32      launch_time = (guint32)-1;
  GSpawnFlags  flags = G_SPAWN_SEARCH_PATH;
  GSpawnChildSetupFunc setup_func = NULL;
  gpointer     setup_data = NULL;

  GPid        *ret_pid = NULL;
  int         *ret_stdin = NULL, *ret_stdout = NULL, *ret_stderr = NULL;
  char       **ret_startup_id = NULL;

  if (documents && desktop_file->document_code == 0)
    {
      g_set_error (error, EGG_DESKTOP_FILE_ERROR,
		   EGG_DESKTOP_FILE_ERROR_NOT_LAUNCHABLE,
		   _("Application does not accept documents on command line"));
      return FALSE;
    }

  /* Read the options: technically it's incorrect for the caller to
   * NULL-terminate the list of options (rather than 0-terminating
   * it), but NULL-terminating lets us use G_GNUC_NULL_TERMINATED,
   * it's more consistent with other glib/gtk methods, and it will
   * work as long as sizeof (int) <= sizeof (NULL), and NULL is
   * represented as 0. (Which is true everywhere we care about.)
   */
  while ((option = va_arg (args, EggDesktopFileLaunchOption)))
    {
      switch (option)
	{
	case EGG_DESKTOP_FILE_LAUNCH_CLEARENV:
	  if (env)
	    g_ptr_array_free (env, TRUE);
	  env = g_ptr_array_new ();
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_PUTENV:
	  variables = va_arg (args, char **);
	  for (i = 0; variables[i]; i++)
	    env = array_putenv (env, variables[i]);
	  break;

	case EGG_DESKTOP_FILE_LAUNCH_SCREEN:
	  screen = va_arg (args, GdkScreen *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_WORKSPACE:
	  workspace = va_arg (args, int);
	  break;

	case EGG_DESKTOP_FILE_LAUNCH_DIRECTORY:
	  directory = va_arg (args, const char *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_TIME:
	  launch_time = va_arg (args, guint32);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_FLAGS:
	  flags |= va_arg (args, GSpawnFlags);
	  /* Make sure they didn't set any flags that don't make sense. */
	  flags &= ~G_SPAWN_FILE_AND_ARGV_ZERO;
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_SETUP_FUNC:
	  setup_func = va_arg (args, GSpawnChildSetupFunc);
	  setup_data = va_arg (args, gpointer);
	  break;

	case EGG_DESKTOP_FILE_LAUNCH_RETURN_PID:
	  ret_pid = va_arg (args, GPid *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDIN_PIPE:
	  ret_stdin = va_arg (args, int *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDOUT_PIPE:
	  ret_stdout = va_arg (args, int *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STDERR_PIPE:
	  ret_stderr = va_arg (args, int *);
	  break;
	case EGG_DESKTOP_FILE_LAUNCH_RETURN_STARTUP_ID:
	  ret_startup_id = va_arg (args, char **);
	  break;

	default:
	  g_set_error (error, EGG_DESKTOP_FILE_ERROR,
		       EGG_DESKTOP_FILE_ERROR_UNRECOGNIZED_OPTION,
		       _("Unrecognized launch option: %d"),
		       GPOINTER_TO_INT (option));
	  success = FALSE;
	  goto out;
	}
    }

  if (screen)
    {
      char *display_name = gdk_screen_make_display_name (screen);
      char *display_env = g_strdup_printf ("DISPLAY=%s", display_name);
      env = array_putenv (env, display_env);
      g_free (display_name);
      g_free (display_env);

      display = gdk_screen_get_display (screen);
    }
  else
    {
      display = gdk_display_get_default ();
      screen = gdk_display_get_default_screen (display);
    }
  screen_num = gdk_screen_get_number (screen);

  translated_documents = translate_document_list (desktop_file, documents);
  docs = translated_documents;

  success = FALSE;

  do
    {
      command = parse_exec (desktop_file, &docs, error);
      if (!command)
	goto out;

      if (!g_shell_parse_argv (command, &argc, &argv, error))
	{
	  g_free (command);
	  goto out;
	}
      g_free (command);

#if GTK_CHECK_VERSION (2, 12, 0)
      startup_id = start_startup_notification (display, desktop_file,
					       argv[0], screen_num,
					       workspace, launch_time);
      if (startup_id)
	{
	  char *startup_id_env = g_strdup_printf ("DESKTOP_STARTUP_ID=%s",
						  startup_id);
	  env = array_putenv (env, startup_id_env);
	  g_free (startup_id_env);
	}
#else
      startup_id = NULL;
#endif /* GTK 2.12 */

      if (env != NULL)
	g_ptr_array_add (env, NULL);

      current_success =
	g_spawn_async_with_pipes (directory,
				  argv,
				  env ? (char **)(env->pdata) : NULL,
				  flags,
				  setup_func, setup_data,
				  ret_pid,
				  ret_stdin, ret_stdout, ret_stderr,
				  error);
      g_strfreev (argv);

      if (startup_id)
	{
#if GTK_CHECK_VERSION (2, 12, 0)
	  if (current_success)
	    {
	      set_startup_notification_timeout (display, startup_id);

	      if (ret_startup_id)
		*ret_startup_id = startup_id;
	      else
		g_free (startup_id);
	    }
	  else
#endif /* GTK 2.12 */
	    g_free (startup_id);
	}
      else if (ret_startup_id)
	*ret_startup_id = NULL;

      if (current_success)
	{
	  /* If we successfully launch any instances of the app, make
	   * sure we return TRUE and don't set @error.
	   */
	  success = TRUE;
	  error = NULL;

	  /* Also, only set the output params on the first one */
	  ret_pid = NULL;
	  ret_stdin = ret_stdout = ret_stderr = NULL;
	  ret_startup_id = NULL;
	}
    }
  while (docs && current_success);

 out:
  if (env)
    {
      g_ptr_array_foreach (env, (GFunc)g_free, NULL);
      g_ptr_array_free (env, TRUE);
    }
  free_document_list (translated_documents);

  return success;
}
int parse_exec(const char* input){
  if(input[0] == '\0'){return 1;}
  int ret = 0;
  int head = 0;
  int pipev = NO_PIPE;
  int pipeline = 0;
  char * parsable = (char *)strdup(input);
  if (parsable == NULL){
    return 1;
  }
  char * command = NULL;
  char * params = NULL;
  char * file = NULL;

  for(;parsable[head] == ' ' || parsable[head] == '\t';head++){}
  int tail = head;
  for(;parsable[head] != '\0';head++){
    if((parsable[head] == ' ' || parsable[head] == '\t') && command == NULL && pipev == NO_PIPE){//first word terminated by space character
      command = (char *)malloc(sizeof(char) *(head - tail + 1));
      if (command == NULL){return 1;}
      if (strncpy(command,parsable + tail,head-tail) == NULL){return 1;}
      command[head-tail] = '\0';
      for(;parsable[head] == ' ' || parsable[head] == '\t';head++){}//discard any extra spaces after the first one
      tail = head;
      head--;//the head is at the next character but is going to get incremented so we must decrement first
    }
    else if((parsable[head] == '<' ||  parsable[head] == '>') && pipev == NO_PIPE){
      if (parsable[head] == '<'){// this has a bug that I don't need to fix because the spec changed
        pipev = PIPE_IN;
      }
      else {
        pipev = PIPE_OUT;
      }
      if (tail != head){
        if(command == NULL){//the first word is terminated with a pipe rather than a space
          command = (char *)malloc(head - tail + 1);
          if (strncpy(command,parsable + tail,head-tail) == NULL){return 1;}
          command[head-tail] = '\0';
          tail = head + 1;//We set the tail ahead of the head so that we don't include the current character
        }
        else {
          int back = head;
          for(;parsable[back] == ' ' || parsable[back] == '\t' || parsable[back] == '>'|| parsable[back] == '<';back--){}
          back++;
          params = (char *)malloc(back - tail + 1);
          if (strncpy(params,parsable + tail,back-tail) == NULL){return 1;}
          params[back-tail] = '\0';
          tail = head + 1;
        }
      }
    }
    else if(parsable[head] == '|'){
      if (pipev != NO_PIPE){//redirect was found first
        for(;parsable[tail] == ' ' || parsable[tail] == '\t';tail++);//no reason to have spaces at head of the redirect file
        if (head != tail){//redirect was not the previous character
          file = (char *)malloc(head - tail + 1);
          if (strncpy(file,parsable + tail,head-tail) == NULL){return 1;}
          file[head-tail] = '\0';
        }
      }
      else if(command == NULL){
        if(tail != head){//the first word is terminated with a pipe rather than a space
          command = (char *)malloc(head - tail + 1);
          if (strncpy(command,parsable + tail,head-tail) == NULL){return 1;}
          command[head-tail] = '\0';
        }
        //this "branch" denotes that the pipe is the first character
      }
      else {// input with params and no redirect or a few other things
        int back = head;
        for(;parsable[back] == ' ' || parsable[back] == '\t' || parsable[back] == '|';back--){}
        back++;
        if(tail < back){
        params = (char *)malloc(back - tail + 1);
        if (strncpy(params,parsable + tail,back-tail) == NULL){return 1;}
        params[back-tail] = '\0';
        }
      }
      pipeline = 1;
      head++;
      tail = head;//Now both head and tail should be set ahead of the pipe
      break;
    }
  }
  if(tail != head){
    if(parsable[tail] == '<' || parsable[tail] == '>' || parsable[tail] == '|'){tail++;}
    for(;tail < strlen(parsable) && (parsable[tail] == ' ' || parsable[tail] == '\t');tail++);
  }
  if(tail != head && pipeline == 0){
    if(pipev == PIPE_IN || pipev == PIPE_OUT){
      file = (char *)malloc(head - tail + 1);
      if (strncpy(file,parsable + tail,head-tail) == NULL){return 1;}
      file[head-tail] = '\0';
      tail = head;
    }
    else if(command == NULL){
      command = (char *)malloc(head - tail + 1);
      if (strncpy(command,parsable + tail,head-tail) == NULL){return 1;}
      command[head-tail] = '\0';
      tail = head;
    }
    else {
      int num = head-tail;
      params = (char *)malloc(sizeof(char)*(head - tail + 1));
      if (strncpy(params,parsable + tail,num) == NULL){return 1;}
      params[head-tail] = '\0';
      tail = head;
    }
  }
  if(DEBUG == 1){
    if(command != NULL){
      printf("Command is: %s\n", command);
    }
    if(params != NULL){
      printf("Params are: %s\n", params);
    }
    if(file != NULL){
      printf("File is: %s\n", file);
    }
    printf("pipev: %d\n",pipev);
    printf("pipeline: %d\n",pipeline);
  }
  int oldredir;
  int pipefile;
  if(pipev == PIPE_IN){
    oldredir = dup(STDIN_FILENO);
    if(file != NULL){
      pipefile = open(file,O_RDONLY);//add file check
      dup2(pipefile,STDIN_FILENO);
      close(pipefile);
    }
  }
  else if(pipev == PIPE_OUT){
    oldredir = dup(STDOUT_FILENO);
    fflush(stdout);
    if(file != NULL){
      pipefile = open(file,O_WRONLY|O_CREAT,0777);
      dup2(pipefile,STDOUT_FILENO);
      close(pipefile);
    }
    else {
      dup2(STDIN_FILENO,STDOUT_FILENO);
    }
  }
  if(pipeline == 1){
    int oldredir2;
    int tubing[2];
    pid_t pid;
    if (pipe(tubing) < 0) {return 1;}
    if ((pid = fork()) < 0) {return 1;}
    else if (pid == 0){
      close(tubing[1]);
      oldredir2 = dup(STDIN_FILENO);
      dup2(tubing[0], STDIN_FILENO);
      ret = parse_exec(&parsable[head]);
      close(tubing[0]);
      dup2(oldredir2, STDIN_FILENO);
      exit(ret);
    }
    else {
      fflush(stdout);
      close(tubing[0]);
      oldredir2 = dup(STDOUT_FILENO);
      dup2(tubing[1], STDOUT_FILENO);
      find_and_exec(command,params);
      fflush(stdout);
      close(tubing[1]);
      dup2(oldredir2, STDOUT_FILENO);
      wait(&ret);
    }
  }
  else{
    ret = find_and_exec(command,params);
  }
  if(pipev == PIPE_IN){
    dup2(oldredir,STDIN_FILENO);
  }
  else if(pipev == PIPE_OUT){
    fflush(stdout);
    dup2(oldredir,STDOUT_FILENO);
  }
  return ret;
}