Skip to content

Instantly share code, notes, and snippets.

@coder3101
Created May 9, 2019 22:07
Show Gist options
  • Save coder3101/37e31ad2c7bcab3f7186ee337ce308d1 to your computer and use it in GitHub Desktop.
Save coder3101/37e31ad2c7bcab3f7186ee337ce308d1 to your computer and use it in GitHub Desktop.
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <sys/inotify.h>
#include <poll.h>
#include <sys/wait.h>
int compile(){
int stat = -1;
int pdd = fork();
if(pdd == -1) {
syslog(LOG_ERR, "Cannot create a fork for Compiler Process");
exit(EXIT_FAILURE);
}
if(pdd == 0){
execl("/bin/g++", "g++", "/home/ashar/Desktop/AutoCompiler/src/sol.cc", "-Wall","-o","/home/ashar/Desktop/AutoCompiler/src/a.out", NULL);
}
else {
syslog(LOG_INFO, "Waiting for compiler process %d to exit", pdd);
waitpid(pdd, &stat, 0);
syslog(LOG_INFO, "Compiler exited with exit code %d", stat);
return 0;
}
return -1;
}
void handle_change(int fd){
char buf[4096] __attribute__((aligned(__alignof__(struct inotify_event))));
const struct inotify_event *event = NULL;
ssize_t len;
char*ptr;
while(1){
len = read(fd, buf, sizeof buf);
if(len == -1 && errno != EAGAIN){
syslog(LOG_ERR, "Failed to read from inotify fd");
exit(EXIT_FAILURE);
}
if(len <= 0) break;
for(ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + event->len){
event = (const struct inotify_event *)ptr;
if(event->mask & IN_CLOSE_WRITE){
compile();
}
else {
if(event->mask == IN_IGNORED){
syslog(LOG_ERR, "Watcher was forcefully removed."
"Did you used vim to save the file without :set backupcopy=yes");
}
else syslog(LOG_WARNING, "Not handling event mask 0x%.8x",event->mask);
}
}
}
}
int main() {
pid_t pid, sid;
pid = fork();
if (pid < 0) {
syslog(LOG_ERR, "Cannot fork daemon process.");
exit(EXIT_FAILURE);
}
if (pid > 0) {
syslog(LOG_INFO, "Fork Success. PID %d", getpid());
exit(EXIT_SUCCESS);
}
umask(0);
int res = setgid(1000); // Run the Daemon on my user group
if(res == -1){
perror("setgid failed");
exit(EXIT_FAILURE);
}
syslog(LOG_INFO, "Starting the AutoCompilerDaemon");
sid = setsid();
if (sid < 0) {
syslog(LOG_ERR, "setsid returned an error");
exit(EXIT_FAILURE);
}
if ((chdir("/")) < 0) {
syslog(LOG_ERR, "chdir to root failed");
exit(EXIT_FAILURE);
}
close(STDIN_FILENO);
//close(STDOUT_FILENO);
//close(STDERR_FILENO);
syslog(LOG_INFO, "Closed all File Descriptors");
syslog(LOG_INFO, "Creating Listener for AutoCompilation of /home/ashar/Desktop/AutoCompiler/src/sol.cc");
int fd = inotify_init1(IN_NONBLOCK);
if(fd == -1){
syslog(LOG_ERR, "Failed to create a inotify instance");
exit(EXIT_FAILURE);
}
int wd = inotify_add_watch(fd, "/home/ashar/Desktop/AutoCompiler/src/sol.cc", IN_CLOSE_WRITE);
if(wd == -1){
syslog(LOG_ERR, "Failed to add the file watcher to inotify instance");
exit(EXIT_FAILURE);
}
syslog(LOG_INFO, "Starting the polling for the change events in the file");
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
syslog(LOG_INFO, "Listening for events on file");
while (1) {
int poll_num = poll(&pfd, 1, -1); // Blocking call
if(poll_num == -1){
if(errno == EINTR) continue; // Interuppts
syslog(LOG_ERR, "Polling Error: Failed to poll for the file for fd changes");
exit(EXIT_FAILURE);
}
if(poll_num > 0){
if(pfd.revents & POLLIN) {
syslog(LOG_INFO, "File Contents have changed. Recompilation begins now");
handle_change(fd);
}
else syslog(LOG_WARNING, "Polling FD is not POLLIN");
}
sleep(30);
}
syslog(LOG_INFO, "Shutting down AutoCompilerDaemon");
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment