示例#1
0
int cmd_search(context_t *context) {
  Window *list;
  xdo_search_t search;
  unsigned int nwindows;
  unsigned int i;
  int c;
  int op_sync = False;

  int search_title = 0;
  int search_name = 0;
  int out_shell = 0;
  char out_prefix[17] = {'\0'};
  int search_class = 0;
  int search_classname = 0;
  typedef enum {
    opt_unused, opt_title, opt_onlyvisible, opt_name, opt_shell, opt_prefix, opt_class, opt_maxdepth,
    opt_pid, opt_help, opt_any, opt_all, opt_screen, opt_classname, opt_desktop,
    opt_limit, opt_sync
  } optlist_t;
  struct option longopts[] = {
    { "all", no_argument, NULL, opt_all },
    { "any", no_argument, NULL, opt_any },
    { "class", no_argument, NULL, opt_class },
    { "classname", no_argument, NULL, opt_classname },
    { "help", no_argument, NULL, opt_help },
    { "maxdepth", required_argument, NULL, opt_maxdepth },
    { "name", no_argument, NULL, opt_name },
    { "shell", no_argument, NULL, opt_shell },
    { "prefix", required_argument, NULL, opt_prefix },
    { "onlyvisible", 0, NULL, opt_onlyvisible },
    { "pid", required_argument, NULL, opt_pid },
    { "screen", required_argument, NULL, opt_screen },
    { "title", no_argument, NULL, opt_title },
    { "desktop", required_argument, NULL, opt_desktop },
    { "limit", required_argument, NULL, opt_limit },
    { "sync", no_argument, NULL, opt_sync },
    { 0, 0, 0, 0 },
  };
  static const char *usage =
      "Usage: xdotool %s "
      "[options] regexp_pattern\n"
      "--class         check regexp_pattern agains the window class\n"
      "--classname     check regexp_pattern agains the window classname\n"
      "--maxdepth N    set search depth to N. Default is infinite.\n"
      "                -1 also means infinite.\n"
      "--onlyvisible   matches only windows currently visible\n"
      "--pid PID       only show windows belonging to specific process\n"
      "                Not supported by all X11 applications\n"
      "--screen N      only search a specific screen. Default is all screens\n"
      "--desktop N     only search a specific desktop number\n"
      "--limit N       break search after N results\n"
      "--name          check regexp_pattern agains the window name\n"
      "--shell         print results as shell array WINDOWS=( ... )\n"
      "--prefix STR    use prefix (max 16 chars) for array name STRWINDOWS\n"
      "--title         DEPRECATED. Same as --name.\n"
      "--all           Require all conditions match a window. Default is --any\n"
      "--any           Windows matching any condition will be reported\n"
      "--sync          Wait until a search result is found.\n"
      "-h, --help      show this help output\n"
      "\n"
      "If none of --name, --classname, or --class are specified, the \n"
      "defaults are: --name --classname --class\n";

  memset(&search, 0, sizeof(xdo_search_t));
  search.max_depth = -1;
  search.require = SEARCH_ANY;

  char *cmd = *context->argv;
  int option_index;

  while ((c = getopt_long_only(context->argc, context->argv, "+h",
                               longopts, &option_index)) != -1) {
    switch (c) {
      case 0:
        break;
      case 'h':
      case opt_help:
        printf(usage, cmd);
        consume_args(context, context->argc);
        return EXIT_SUCCESS;
      case opt_maxdepth:
        search.max_depth = strtol(optarg, NULL, 0);
        break;
      case opt_pid:
        search.pid = atoi(optarg);
        search.searchmask |= SEARCH_PID;
        break;
      case opt_any:
        search.require = SEARCH_ANY;
        break;
      case opt_all:
        search.require = SEARCH_ALL;
        break;
      case opt_screen:
        search.screen = strtoul(optarg, NULL, 0);
        search.searchmask |= SEARCH_SCREEN;
        break;
      case opt_onlyvisible:
        search.only_visible = True;
        search.searchmask |= SEARCH_ONLYVISIBLE;
        break;
      case opt_class:
        search_class = True;
        break;
      case opt_classname:
        search_classname = True;
        break;
      case opt_title:
        fprintf(stderr, "This flag is deprecated. Assuming you mean --name (the"
                " window name).\n");
        /* fall through */
      case opt_name:
        search_name = True;
        break;
      case opt_shell:
        out_shell = True;
        break;
      case opt_prefix:
        strncpy(out_prefix, optarg, sizeof(out_prefix)-1);
        out_prefix[ sizeof(out_prefix)-1 ] = '\0'; //just in case
        break;
      case opt_desktop:
        search.desktop = strtol(optarg, NULL, 0);
        search.searchmask |= SEARCH_DESKTOP;
        break;
      case opt_limit:
        search.limit = atoi(optarg);
        break;
      case opt_sync:
        op_sync = True;
        break;
      default:
        fprintf(stderr, "Invalid usage\n");
        fprintf(stderr, usage, cmd);
        return EXIT_FAILURE;
    }
  }

  consume_args(context, optind);

  /* We require a pattern or a pid to search for */
  if (context->argc < 1 && search.pid == 0) {
    fprintf(stderr, usage, cmd);
    return EXIT_FAILURE;
  }

  if (context->argc > 0) {
    if (!search_title && !search_name && !search_class && !search_classname) {
      fprintf(stderr, "Defaulting to search window name, class, and classname\n");
      search.searchmask |= (SEARCH_NAME | SEARCH_CLASS | SEARCH_CLASSNAME);
      search_name = 1;
      search_class = 1;
      search_classname = 1;
    }

    if (search_title) {
      search.searchmask |= SEARCH_NAME;
      search.winname = context->argv[0];
    }
    if (search_name) {
      search.searchmask |= SEARCH_NAME;
      search.winname = context->argv[0];
    }
    if (search_class) {
      search.searchmask |= SEARCH_CLASS;
      search.winclass = context->argv[0];
    }
    if (search_classname) {
      search.searchmask |= SEARCH_CLASSNAME;
      search.winclassname = context->argv[0];
    }
    consume_args(context, 1);
  }

  do {
    xdo_search_windows(context->xdo, &search, &list, &nwindows);

    if ( (context->argc == 0) || out_shell ) {
      /* only print if we're the last command or printing to shell*/
      if (out_shell) printf("%s%s", out_prefix, "WINDOWS=(");
      for (i = 0; i < nwindows; i++) {
        window_print(list[i]);
      }
      if (out_shell) printf("%s",")\n");
    }

    if (op_sync && nwindows == 0) {
      xdotool_debug(context, "No search results, still waiting...");

      /* TODO(sissel): Make this tunable */
      usleep(500000);
    }
  } while (op_sync && nwindows == 0);

  /* Free old list as it's malloc'd by xdo_search_windows */
  if (context->windows != NULL) {
    free(context->windows);
  }
  context->windows = list;
  context->nwindows = nwindows;

  /* error if number of windows found is zero (behave like grep) 
  but return success when being used inside eval (--shell option)*/
  return (nwindows || out_shell ? EXIT_SUCCESS : EXIT_FAILURE);
}
示例#2
0
int cmd_exec(context_t *context) {
  char *cmd = *context->argv;
  char **command = NULL;
  int command_count = 0;
  int ret = EXIT_SUCCESS;
  int opsync = 0;
  int arity = -1;
  char *terminator = NULL;
  int c, i;

  typedef enum {
    opt_unused, opt_help, opt_sync, opt_args, opt_terminator
  } optlist_t;
  static struct option longopts[] = {
    { "help", no_argument, NULL, opt_help },
    { "sync", no_argument, NULL, opt_sync },
    { "args", required_argument, NULL, opt_args },
    { "terminator", required_argument, NULL, opt_terminator },
    { 0, 0, 0, 0 },
  };
  static const char *usage = 
    "Usage: %s [options] command [arg1 arg2 ...] [terminator]\n"
    "--sync    - only exit when the command given finishes. The default\n"
    "            is to fork a child process and continue.\n"
    "--args N  - how many arguments to expect in the exec command. This is\n"
    "            useful for ending an exec and continuing with more xdotool\n"
    "            commands\n"
    "--terminator TERM - similar to --args, specifies a terminator that\n"
    "                    marks the end of 'exec' arguments. This is useful\n"
    "                    for continuing with more xdotool commands.\n"
    "\n"
    "Unless --args OR --terminator is specified, the exec command is assumed\n"
    "to be the remainder of the command line.\n";
  
  int option_index;
  while ((c = getopt_long_only(context->argc, context->argv, "+h",
                               longopts, &option_index)) != -1) {
    switch (c) {
      case 'h':
      case opt_help:
        printf(usage, cmd);
        consume_args(context, context->argc);
        return EXIT_SUCCESS;
        break;
      case opt_sync:
        opsync = 1;
        break;
      case opt_args:
        arity = atoi(optarg);
        break;
      case opt_terminator:
        terminator = strdup(optarg);
        break;
      default:
        fprintf(stderr, usage, cmd);
        return EXIT_FAILURE;
    }
  }

  consume_args(context, optind);

  if (context->argc == 0) {
    fprintf(stderr, "No arguments given.\n");
    fprintf(stderr, usage, cmd);
    return EXIT_FAILURE;
  }

  if (arity > 0 && terminator != NULL) {
    fprintf(stderr, "Don't use both --terminator and --args.\n");
    return EXIT_FAILURE;
  }

  if (context->argc < arity) {
    fprintf(stderr, "You said '--args %d' but only gave %d arguments.\n",
            arity, context->argc);
    return EXIT_FAILURE;
  }

  command = calloc(context->argc + 1, sizeof(char *));

  for (i=0; i < context->argc; i++) {
    if (arity > 0 && i == arity) {
      break;
    }

    /* if we have a terminator and the current argument matches it... */
    if (terminator != NULL && strcmp(terminator, context->argv[i]) == 0) {
      command_count++; /* Consume the terminator, too */
      break;
    }

    command[i] = strdup(context->argv[i]);
    command_count = i + 1; /* i starts at 0 */
    xdotool_debug(context, "Exec arg[%d]: %s", i, command[i]);
  }
  command[i] = NULL;
  
  pid_t child;
  child = fork();
  if (child == 0) { /* child */
    execvp(command[0], command);

    /* if we get here, there was an error */
    perror("execvp failed");
    exit(errno);
  } else { /* parent */
    if (opsync) {
      int status = 0;
      waitpid(child, &status, 0);
      ret = WEXITSTATUS(status);
    }
  }

  consume_args(context, command_count);
  if (terminator != NULL) {
    free(terminator);
  }

  for (i=0; i < command_count; i++) {
    free(command[i]);
  }
  free(command);
  return ret;
}
示例#3
0
文件: cmd_type.c 项目: KoFish/xdotool
int cmd_type(context_t *context) {
  int ret = 0;
  int i;
  int c;
  char *cmd = *context->argv;
  char *window_arg = NULL;
  int arity = -1;
  char *terminator = NULL;
  char *file = NULL;

  FILE *input = NULL;
  char *buffer = NULL;
  char *marker = NULL;
  size_t bytes_read = 0;

  char **data = NULL; /* stuff to type */
  int data_count = 0;
  int args_count = 0;
  charcodemap_t *active_mods = NULL;
  int active_mods_n;

  /* Options */
  int clear_modifiers = 0;
  useconds_t delay = 12000; /* 12ms between keystrokes default */

  typedef enum {
    opt_unused, opt_clearmodifiers, opt_delay, opt_help, opt_window, opt_args,
    opt_terminator, opt_file
  } optlist_t;

  struct option longopts[] = {
    { "clearmodifiers", no_argument, NULL, opt_clearmodifiers },
    { "delay", required_argument, NULL, opt_delay },
    { "help", no_argument, NULL, opt_help },
    { "window", required_argument, NULL, opt_window },
    { "args", required_argument, NULL, opt_args },
    { "terminator", required_argument, NULL, opt_terminator },
    { "file", required_argument, NULL, opt_file },
    { 0, 0, 0, 0 },
  };

  static const char *usage =
    "Usage: %s [--window windowid] [--delay milliseconds] "
    "<things to type>\n"
    "--window <windowid>    - specify a window to send keys to\n"
    "--delay <milliseconds> - delay between keystrokes\n"
    "--clearmodifiers       - reset active modifiers (alt, etc) while typing\n"
    "--args N  - how many arguments to expect in the exec command. This is\n"
    "            useful for ending an exec and continuing with more xdotool\n"
    "            commands\n"
    "--terminator TERM - similar to --args, specifies a terminator that\n"
    "                    marks the end of 'exec' arguments. This is useful\n"
    "                    for continuing with more xdotool commands.\n"
    "--file <filepath> - specify a file, the contents of which will be\n"
    "                    be typed as if passed as an argument. The filepath\n"
    "                    may also be '-' to read from stdin.\n"
            "-h, --help             - show this help output\n";
  int option_index;

  while ((c = getopt_long_only(context->argc, context->argv, "+w:d:ch",
                               longopts, &option_index)) != -1) {
    switch (c) {
      case opt_window:
        window_arg = strdup(optarg);
        break;
      case opt_delay:
        /* --delay is in milliseconds, convert to microseconds */
        delay = strtoul(optarg, NULL, 0) * 1000;
        break;
      case opt_clearmodifiers:
        clear_modifiers = 1;
        break;
      case opt_help:
        printf(usage, cmd);
        consume_args(context, context->argc);
        return EXIT_SUCCESS;
        break;
      case opt_args:
        arity = atoi(optarg);
        break;
      case opt_terminator:
        terminator = strdup(optarg);
        break;
      case opt_file:
	file = strdup(optarg);
	break;
      default:
        fprintf(stderr, usage, cmd);
        return EXIT_FAILURE;
    }
  }

  consume_args(context, optind);

  if (context->argc == 0 && file == NULL) {
    fprintf(stderr, "You specified the wrong number of args.\n");
    fprintf(stderr, usage, cmd);
    return 1;
  }

  if (arity > 0 && terminator != NULL) {
    fprintf(stderr, "Don't use both --terminator and --args.\n");
    return EXIT_FAILURE;
  }

  if (context->argc < arity) {
    fprintf(stderr, "You said '--args %d' but only gave %d arguments.\n",
            arity, context->argc);
    return EXIT_FAILURE;
  }

  if (file != NULL) {
    data = calloc(1 + context->argc, sizeof(char *));

    /* determine whether reading from a file or from stdin */
    if (!strcmp(file, "-")) {
      input = fdopen(0, "r");
    } else {
      input = fopen(file, "r");
      if (input == NULL) {
        fprintf(stderr, "Failure opening '%s': %s\n", file, strerror(errno));
        return EXIT_FAILURE;
      }
    }

    while (feof(input) == 0) {
      marker = realloc(buffer, bytes_read + 4096);
      if (marker == NULL) {
        fprintf(stderr, "Failure allocating for '%s': %s\n", file, strerror(errno));
        return EXIT_FAILURE;
      }

      buffer = marker;
      marker = buffer + bytes_read;
      if (fgets(marker, 4096, input) != NULL) {
        bytes_read = (marker - buffer) + strlen(marker);
      }

      if (ferror(input) != 0) {
        fprintf(stderr, "Failure reading '%s': %s\n", file, strerror(errno));
        return EXIT_FAILURE;
      }
    }

    data[0] = buffer;
    data_count++;

    fclose(input);
  }
  else {
    data = calloc(context->argc, sizeof(char *));
  }

  /* Apply any --arity or --terminator */
  for (i=0; i < context->argc; i++) {
    if (arity > 0 && i == arity) {
      data[data_count] = NULL;
      break;
    }

    /* if we have a terminator and the current argument matches it... */
    if (terminator != NULL && strcmp(terminator, context->argv[i]) == 0) {
      data[data_count] = NULL;
      args_count++; /* Consume the terminator, too */
      break;
    }

    data[data_count] = strdup(context->argv[i]);
    xdotool_debug(context, "Exec arg[%d]: %s", i, data[data_count]);
    data_count++;
    args_count++;
  }

  window_each(context, window_arg, {
    if (clear_modifiers) {
      xdo_get_active_modifiers(context->xdo, &active_mods, &active_mods_n);
      xdo_clear_active_modifiers(context->xdo, window, active_mods, active_mods_n);
    }

    for (i = 0; i < data_count; i++) {
      //printf("Typing: '%s'\n", context->argv[i]);
      int tmp = xdo_enter_text_window(context->xdo, window, data[i], delay);

      if (tmp) {
        fprintf(stderr, "xdo_enter_text_window reported an error\n");
      }

      ret += tmp;
    }

    if (clear_modifiers) {
      xdo_set_active_modifiers(context->xdo, window, active_mods, active_mods_n);
      free(active_mods);
    }
  }); /* window_each(...) */