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