bool parse_opts( int * argc, char *** argv, int * events, bool * monitor, int * quiet, unsigned long int * timeout, int * recursive, bool * csv, bool * daemon, bool * syslog, char ** format, char ** timefmt, char ** fromfile, char ** outfile, char ** regex, char ** iregex ) { assert( argc ); assert( argv ); assert( events ); assert( monitor ); assert( quiet ); assert( timeout ); assert( csv ); assert( daemon ); assert( syslog ); assert( format ); assert( timefmt ); assert( fromfile ); assert( outfile ); assert( regex ); assert( iregex ); // Short options char * opt_string = "mrhcdsqt:fo:e:"; // Construct array struct option long_opts[17]; // --help long_opts[0].name = "help"; long_opts[0].has_arg = 0; long_opts[0].flag = NULL; long_opts[0].val = (int)'h'; // --event long_opts[1].name = "event"; long_opts[1].has_arg = 1; long_opts[1].flag = NULL; long_opts[1].val = (int)'e'; int new_event; // --monitor long_opts[2].name = "monitor"; long_opts[2].has_arg = 0; long_opts[2].flag = NULL; long_opts[2].val = (int)'m'; // --quiet long_opts[3].name = "quiet"; long_opts[3].has_arg = 0; long_opts[3].flag = NULL; long_opts[3].val = (int)'q'; // --timeout long_opts[4].name = "timeout"; long_opts[4].has_arg = 1; long_opts[4].flag = NULL; long_opts[4].val = (int)'t'; char * timeout_end = NULL; // --filename long_opts[5].name = "filename"; long_opts[5].has_arg = 0; long_opts[5].flag = NULL; long_opts[5].val = (int)'f'; // --recursive long_opts[6].name = "recursive"; long_opts[6].has_arg = 0; long_opts[6].flag = NULL; long_opts[6].val = (int)'r'; // --csv long_opts[7].name = "csv"; long_opts[7].has_arg = 0; long_opts[7].flag = NULL; long_opts[7].val = (int)'c'; // --daemon long_opts[8].name = "daemon"; long_opts[8].has_arg = 0; long_opts[8].flag = NULL; long_opts[8].val = (int)'d'; // --syslog long_opts[9].name = "syslog"; long_opts[9].has_arg = 0; long_opts[9].flag = NULL; long_opts[9].val = (int)'s'; // --format long_opts[10].name = "format"; long_opts[10].has_arg = 1; long_opts[10].flag = NULL; long_opts[10].val = (int)'n'; // format with trailing newline static char * newlineformat; // --timefmt long_opts[11].name = "timefmt"; long_opts[11].has_arg = 1; long_opts[11].flag = NULL; long_opts[11].val = (int)'i'; // --fromfile long_opts[12].name = "fromfile"; long_opts[12].has_arg = 1; long_opts[12].flag = NULL; long_opts[12].val = (int)'z'; // --outfile long_opts[13].name = "outfile"; long_opts[13].has_arg = 1; long_opts[13].flag = NULL; long_opts[13].val = (int)'o'; // --exclude long_opts[14].name = "exclude"; long_opts[14].has_arg = 1; long_opts[14].flag = NULL; long_opts[14].val = (int)'a'; // --excludei long_opts[15].name = "excludei"; long_opts[15].has_arg = 1; long_opts[15].flag = NULL; long_opts[15].val = (int)'b'; // Empty last element long_opts[16].name = 0; long_opts[16].has_arg = 0; long_opts[16].flag = 0; long_opts[16].val = 0; // Get first option char curr_opt = getopt_long(*argc, *argv, opt_string, long_opts, NULL); // While more options exist... while ( (curr_opt != '?') && (curr_opt != (char)-1) ) { switch ( curr_opt ) { // --help or -h case 'h': print_help(); // Shouldn't process any further... return false; break; // --monitor or -m case 'm': *monitor = true; break; // --quiet or -q case 'q': (*quiet)++; break; // --recursive or -r case 'r': (*recursive)++; break; // --csv or -c case 'c': (*csv) = true; break; // --daemon or -d case 'd': (*daemon) = true; (*monitor) = true; (*syslog) = true; break; // --syslog or -s case 's': (*syslog) = true; break; // --filename or -f case 'f': fprintf(stderr, "The '--filename' option no longer exists. " "The option it enabled in earlier\nversions of " "inotifywait is now turned on by default.\n"); return false; break; // --format case 'n': newlineformat = (char *)malloc(strlen(optarg)+2); strcpy( newlineformat, optarg ); strcat( newlineformat, "\n" ); (*format) = newlineformat; break; // --timefmt case 'i': (*timefmt) = optarg; break; // --exclude case 'a': (*regex) = optarg; break; // --excludei case 'b': (*iregex) = optarg; break; // --fromfile case 'z': if (*fromfile) { fprintf(stderr, "Multiple --fromfile options given.\n"); return false; } (*fromfile) = optarg; break; // --outfile case 'o': if (*outfile) { fprintf(stderr, "Multiple --outfile options given.\n"); return false; } (*outfile) = optarg; break; // --timeout or -t case 't': *timeout = strtoul(optarg, &timeout_end, 10); if ( *timeout_end != '\0' ) { fprintf(stderr, "'%s' is not a valid timeout value.\n" "Please specify an integer of value 0 or " "greater.\n", optarg); return false; } break; // --event or -e case 'e': // Get event mask from event string new_event = inotifytools_str_to_event(optarg); // If optarg was invalid, abort if ( new_event == -1 ) { fprintf(stderr, "'%s' is not a valid event! Run with the " "'--help' option to see a list of " "events.\n", optarg); return false; } // Add the new event to the event mask (*events) = ( (*events) | new_event ); break; } curr_opt = getopt_long(*argc, *argv, opt_string, long_opts, NULL); } if ( *monitor && *timeout != 0 ) { fprintf(stderr, "-m and -t cannot both be specified.\n"); return false; } if ( *regex && *iregex ) { fprintf(stderr, "--exclude and --excludei cannot both be specified.\n"); return false; } if ( *format && *csv ) { fprintf(stderr, "-c and --format cannot both be specified.\n"); return false; } if ( !*format && *timefmt ) { fprintf(stderr, "--timefmt cannot be specified without --format.\n"); return false; } if ( *format && strstr( *format, "%T" ) && !*timefmt ) { fprintf(stderr, "%%T is in --format string, but --timefmt was not " "specified.\n"); return false; } if ( *daemon && *outfile == NULL ) { fprintf(stderr, "-o must be specified with -d.\n"); return false; } (*argc) -= optind; *argv = &(*argv)[optind]; // If ? returned, invalid option return (curr_opt != '?'); }
bool parse_opts( int * argc, char *** argv, int * events, int * timeout, int * verbose, int * zero, int * sort, int * recursive, char ** fromfile, char ** regex, char ** iregex ) { assert( argc ); assert( argv ); assert( events ); assert( timeout ); assert( verbose ); assert( zero ); assert( sort ); assert( recursive ); assert( fromfile ); assert( regex ); assert( iregex ); // Short options char * opt_string = "hra:d:zve:t:"; // Construct array struct option long_opts[12]; // --help long_opts[0].name = "help"; long_opts[0].has_arg = 0; long_opts[0].flag = NULL; long_opts[0].val = (int)'h'; // --event long_opts[1].name = "event"; long_opts[1].has_arg = 1; long_opts[1].flag = NULL; long_opts[1].val = (int)'e'; int new_event; // --timeout long_opts[2].name = "timeout"; long_opts[2].has_arg = 1; long_opts[2].flag = NULL; long_opts[2].val = (int)'t'; char * timeout_end = NULL; // --verbose long_opts[3].name = "verbose"; long_opts[3].has_arg = 0; long_opts[3].flag = NULL; long_opts[3].val = (int)'v'; // --nonzero long_opts[4].name = "zero"; long_opts[4].has_arg = 0; long_opts[4].flag = NULL; long_opts[4].val = (int)'z'; // --ascending long_opts[5].name = "ascending"; long_opts[5].has_arg = 1; long_opts[5].flag = NULL; long_opts[5].val = (int)'a'; bool sort_set = false; // --descending long_opts[6].name = "descending"; long_opts[6].has_arg = 1; long_opts[6].flag = NULL; long_opts[6].val = (int)'d'; // --recursive long_opts[7].name = "recursive"; long_opts[7].has_arg = 0; long_opts[7].flag = NULL; long_opts[7].val = (int)'r'; // --fromfile long_opts[8].name = "fromfile"; long_opts[8].has_arg = 1; long_opts[8].flag = NULL; long_opts[8].val = (int)'o'; // --exclude long_opts[9].name = "exclude"; long_opts[9].has_arg = 1; long_opts[9].flag = NULL; long_opts[9].val = (int)'c'; // --excludei long_opts[10].name = "excludei"; long_opts[10].has_arg = 1; long_opts[10].flag = NULL; long_opts[10].val = (int)'b'; // Empty last element long_opts[11].name = 0; long_opts[11].has_arg = 0; long_opts[11].flag = 0; long_opts[11].val = 0; // Get first option char curr_opt = getopt_long(*argc, *argv, opt_string, long_opts, NULL); // While more options exist... while ( (curr_opt != '?') && (curr_opt != (char)-1) ) { switch ( curr_opt ) { // --help or -h case 'h': print_help(); // Shouldn't process any further... return false; break; // --verbose or -v case 'v': ++(*verbose); break; // --recursive or -r case 'r': ++(*recursive); break; // --zero or -z case 'z': ++(*zero); break; // --exclude case 'c': (*regex) = optarg; break; // --excludei case 'b': (*iregex) = optarg; break; // --fromfile case 'o': if (*fromfile) { fprintf(stderr, "Multiple --fromfile options given.\n"); return false; } (*fromfile) = optarg; break; // --timeout or -t case 't': *timeout = strtoul(optarg, &timeout_end, 10); if ( *timeout_end != '\0' || *timeout < 0) { fprintf(stderr, "'%s' is not a valid timeout value.\n" "Please specify an integer of value 0 or " "greater.\n", optarg); return false; } break; // --event or -e case 'e': // Get event mask from event string new_event = inotifytools_str_to_event(optarg); // If optarg was invalid, abort if ( new_event == -1 ) { fprintf(stderr, "'%s' is not a valid event! Run with the " "'--help' option to see a list of " "events.\n", optarg); return false; } // Add the new event to the event mask (*events) = ( (*events) | new_event ); break; // --ascending or -a case 'a': if ( sort_set ) { fprintf( stderr, "Please specify -a or -d once only!\n" ); return false; } if ( 0 == strcasecmp( optarg, "total" ) ) { (*sort) = 0; } else if ( 0 == strcasecmp( optarg, "move" ) ) { fprintf( stderr, "Cannot sort by `move' event; please use " "`moved_from' or `moved_to'.\n" ); return false; } else if ( 0 == strcasecmp( optarg, "close" ) ) { fprintf( stderr, "Cannot sort by `close' event; please use " "`close_write' or `close_nowrite'.\n" ); return false; } else { int event = inotifytools_str_to_event(optarg); // If optarg was invalid, abort if ( event == -1 ) { fprintf(stderr, "'%s' is not a valid key for " "sorting!\n", optarg); return false; } (*sort) = event; } sort_set = true; break; // --descending or -d case 'd': if ( sort_set ) { fprintf( stderr, "Please specify -a or -d once only!\n" ); return false; } if ( 0 == strcasecmp( optarg, "total" ) ) { (*sort) = -1; } else { int event = inotifytools_str_to_event(optarg); // If optarg was invalid, abort if ( event == -1 ) { fprintf(stderr, "'%s' is not a valid key for " "sorting!\n", optarg); return false; } (*sort) = -event; } break; } curr_opt = getopt_long(*argc, *argv, opt_string, long_opts, NULL); } (*argc) -= optind; *argv = &(*argv)[optind]; if ( (*sort) != 0 && (*sort) != -1 && !(abs(*sort) & ((*events) ? (*events) : IN_ALL_EVENTS) )) { fprintf( stderr, "Can't sort by an event which isn't being watched " "for!\n" ); return false; } if ( *regex && *iregex ) { fprintf(stderr, "--exclude and --excludei cannot both be specified.\n"); return false; } // If ? returned, invalid option return (curr_opt != '?'); }
void str_to_event() { ENTER compare(inotifytools_str_to_event("open,modify,access"), IN_OPEN | IN_MODIFY | IN_ACCESS); compare(inotifytools_str_to_event(",open,modify,access"), 0); compare(inotifytools_str_to_event("open,modify,access,"), 0); compare(inotifytools_str_to_event("open,modify,,access,close"), 0); compare(inotifytools_str_to_event("open,mod,access,close"), -1); compare(inotifytools_str_to_event("mod"), -1); compare(inotifytools_str_to_event(","), 0); compare(inotifytools_str_to_event(",,"), 0); compare(inotifytools_str_to_event("open"), IN_OPEN); compare(inotifytools_str_to_event("close"), IN_CLOSE); compare(inotifytools_str_to_event(",close"), 0); compare(inotifytools_str_to_event(",,close"), 0); compare(inotifytools_str_to_event("close,"), 0); compare(inotifytools_str_to_event("close,,"), 0); EXIT }