cli.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include <getopt.h>
  2. #include "cli.h"
  3. const char* cli_info_purpose = "A flexible command-line interface for the FSEvents API";
  4. const char* cli_info_usage = "Usage: fsevent_watch [OPTIONS]... [PATHS]...";
  5. const char* cli_info_help[] = {
  6. " -h, --help you're looking at it",
  7. " -V, --version print version number and exit",
  8. " -p, --show-plist display the embedded Info.plist values",
  9. " -s, --since-when=EventID fire historical events since ID",
  10. " -l, --latency=seconds latency period (default='0.5')",
  11. " -n, --no-defer enable no-defer latency modifier",
  12. " -r, --watch-root watch for when the root path has changed",
  13. // " -i, --ignore-self ignore current process",
  14. " -F, --file-events provide file level event data",
  15. " -f, --format=name output format (ignored)",
  16. 0
  17. };
  18. static void default_args (struct cli_info* args_info)
  19. {
  20. args_info->since_when_arg = kFSEventStreamEventIdSinceNow;
  21. args_info->latency_arg = 0.5;
  22. args_info->no_defer_flag = false;
  23. args_info->watch_root_flag = false;
  24. args_info->ignore_self_flag = false;
  25. args_info->file_events_flag = false;
  26. args_info->mark_self_flag = false;
  27. args_info->format_arg = 0;
  28. }
  29. static void cli_parser_release (struct cli_info* args_info)
  30. {
  31. unsigned int i;
  32. for (i=0; i < args_info->inputs_num; ++i) {
  33. free(args_info->inputs[i]);
  34. }
  35. if (args_info->inputs_num) {
  36. free(args_info->inputs);
  37. }
  38. args_info->inputs_num = 0;
  39. }
  40. void cli_parser_init (struct cli_info* args_info)
  41. {
  42. default_args(args_info);
  43. args_info->inputs = 0;
  44. args_info->inputs_num = 0;
  45. }
  46. void cli_parser_free (struct cli_info* args_info)
  47. {
  48. cli_parser_release(args_info);
  49. }
  50. static void cli_print_info_dict (const void *key,
  51. const void *value,
  52. void *context)
  53. {
  54. CFStringRef entry = CFStringCreateWithFormat(NULL, NULL,
  55. CFSTR("%@:\n %@"), key, value);
  56. if (entry) {
  57. CFShow(entry);
  58. CFRelease(entry);
  59. }
  60. }
  61. void cli_show_plist (void)
  62. {
  63. CFBundleRef mainBundle = CFBundleGetMainBundle();
  64. CFRetain(mainBundle);
  65. CFDictionaryRef mainBundleDict = CFBundleGetInfoDictionary(mainBundle);
  66. if (mainBundleDict) {
  67. CFRetain(mainBundleDict);
  68. printf("Embedded Info.plist metadata:\n\n");
  69. CFDictionaryApplyFunction(mainBundleDict, cli_print_info_dict, NULL);
  70. CFRelease(mainBundleDict);
  71. }
  72. CFRelease(mainBundle);
  73. printf("\n");
  74. }
  75. void cli_print_version (void)
  76. {
  77. printf("%s %s\n\n", "VXZ", "1.0");
  78. }
  79. void cli_print_help (void)
  80. {
  81. cli_print_version();
  82. printf("\n%s\n", cli_info_purpose);
  83. printf("\n%s\n", cli_info_usage);
  84. printf("\n");
  85. int i = 0;
  86. while (cli_info_help[i]) {
  87. printf("%s\n", cli_info_help[i++]);
  88. }
  89. }
  90. int cli_parser (int argc, const char** argv, struct cli_info* args_info)
  91. {
  92. static struct option longopts[] = {
  93. { "help", no_argument, NULL, 'h' },
  94. { "version", no_argument, NULL, 'V' },
  95. { "show-plist", no_argument, NULL, 'p' },
  96. { "since-when", required_argument, NULL, 's' },
  97. { "latency", required_argument, NULL, 'l' },
  98. { "no-defer", no_argument, NULL, 'n' },
  99. { "watch-root", no_argument, NULL, 'r' },
  100. { "ignore-self", no_argument, NULL, 'i' },
  101. { "file-events", no_argument, NULL, 'F' },
  102. { "mark-self", no_argument, NULL, 'm' },
  103. { "format", required_argument, NULL, 'f' },
  104. { 0, 0, 0, 0 }
  105. };
  106. const char* shortopts = "hVps:l:nriFf:";
  107. int c = -1;
  108. while ((c = getopt_long(argc, (char * const*)argv, shortopts, longopts, NULL)) != -1) {
  109. switch(c) {
  110. case 's': // since-when
  111. args_info->since_when_arg = strtoull(optarg, NULL, 0);
  112. break;
  113. case 'l': // latency
  114. args_info->latency_arg = strtod(optarg, NULL);
  115. break;
  116. case 'n': // no-defer
  117. args_info->no_defer_flag = true;
  118. break;
  119. case 'r': // watch-root
  120. args_info->watch_root_flag = true;
  121. break;
  122. case 'i': // ignore-self
  123. args_info->ignore_self_flag = true;
  124. break;
  125. case 'F': // file-events
  126. args_info->file_events_flag = true;
  127. break;
  128. case 'm': // mark-self
  129. args_info->mark_self_flag = true;
  130. break;
  131. case 'f': // format
  132. // XXX: ignored
  133. break;
  134. case 'V': // version
  135. cli_print_version();
  136. exit(EXIT_SUCCESS);
  137. case 'p': // show-plist
  138. cli_show_plist();
  139. exit(EXIT_SUCCESS);
  140. case 'h': // help
  141. case '?': // invalid option
  142. case ':': // missing argument
  143. cli_print_help();
  144. exit((c == 'h') ? EXIT_SUCCESS : EXIT_FAILURE);
  145. }
  146. }
  147. if (optind < argc) {
  148. int i = 0;
  149. args_info->inputs_num = (unsigned int)(argc - optind);
  150. args_info->inputs =
  151. (char**)(malloc ((args_info->inputs_num)*sizeof(char*)));
  152. while (optind < argc)
  153. if (argv[optind++] != argv[0]) {
  154. args_info->inputs[i++] = strdup(argv[optind-1]);
  155. }
  156. }
  157. return EXIT_SUCCESS;
  158. }