/* inotifyrun Copyright (C) 2020 niansa This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "license.h" #include "libcatch/libcatch.h" struct fcmd_pair { const char *fname; const char *command; }; struct fcmdwatcher_pair { struct fcmd_pair *pair; int watcher; }; int main(int argc, char **argv) { int inotifier; libcatch_init(); // Check arguments if (argc == 2 && strcmp(argv[1], "--license") == 0) { // License requested puts(gpl3); return EXIT_SUCCESS; } else if (argc == 1 || (argc - 1) % 2 != 0) { // No arguments passed printf("Usage: %s [--license] { }\n", argv[0]); return EXIT_FAILURE; } // Initialise inotify CATCH1( inotifier = inotify_init() ); // Get array of files and commands libcatch_behavior = 0; struct fcmd_pair *assocs = (struct fcmd_pair *)(argv + 1); struct fcmdwatcher_pair *assocs_watches; struct fcmdwatcher_pair *watcherpair_ptr; CATCH1(assocs_watches = malloc((sizeof(struct fcmdwatcher_pair) * ((argc - 1) / 2)) + 1)); // Initlialise inotify further while checking if all files are actual files libcatch_behavior = 2; for (struct fcmd_pair *thispair = assocs; *(char**)thispair; thispair++) { // Check if file is an actual file struct stat fname_stat; stat(thispair->fname, &fname_stat); if (S_ISDIR(fname_stat.st_mode)) { fprintf(stderr, "'%s' is a directory and will be ignored.\n", thispair->fname); continue; } // Initialise inotify further watcherpair_ptr = &assocs_watches[thispair - assocs]; watcherpair_ptr->pair = thispair; CATCH1( watcherpair_ptr->watcher = inotify_add_watch(inotifier, thispair->fname, IN_OPEN) ); } // Wait for events to occur libcatch_behavior = 1; struct inotify_event thisevent; while (1) { // Read new event CATCH1( read(inotifier, &thisevent, sizeof(thisevent) + NAME_MAX + 1) ); // Find associated event pair for ( watcherpair_ptr = assocs_watches; watcherpair_ptr->watcher != thisevent.wd; watcherpair_ptr++ ); // Run assiciated command system(watcherpair_ptr->pair->command); } }