inotifyrun/inotifyrun.c
2020-10-11 17:30:45 +02:00

98 lines
2.9 KiB
C

/*
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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/inotify.h>
#include <linux/fs.h>
#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();
//int *p = NULL; *p = 1; //DEBUG
//*p = 1; //DEBUG
// 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] {<file> <command>}\n", argv[0]);
return EXIT_FAILURE;
}
// Initialise inotify
CATCH(
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 = malloc((sizeof(struct fcmdwatcher_pair) * ((argc - 1) / 2)) + 1);
struct fcmdwatcher_pair *watcherpair_ptr;
CATCH(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;
CATCH(
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
CATCH(
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);
}
}