//============================================================================ // Name : Daemon.cpp // Author : Jarek Szymczak // Version : // Copyright : // Description : Database data adding from files daemon //============================================================================ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define EVENT_SIZE ( sizeof (struct inotify_event) ) #define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) #define RUNNING_DIR "/opt/app/gssim/daemon" #define LOCK_FILE "daemon.lock" #define LOG_FILE "daemon.log" int fd; int length; int wd; char buffer[EVENT_BUF_LEN]; char gssimdir[255]; char gssimexecfile[255]; char basedir[255]; char msg[255]; map paths; void log_message(const char *filename, const char *message) { FILE *logfile; logfile=fopen(filename,"a"); if(!logfile) return; fprintf(logfile,"%s\n",message); fclose(logfile); } bool file_exists(const char * filename) { if (FILE * file = fopen(filename, "r")) { fclose(file); return true; } return false; } void signal_handler(int sig) { close(fd); fclose (stdout); fclose (stderr); switch(sig) { case SIGHUP: log_message(LOG_FILE, "hangup signal catched"); break; case SIGTERM: log_message(LOG_FILE,"terminate signal catched"); exit(0); break; } } void daemonize() { int i,lfp; char str[10]; lfp=open(LOCK_FILE,O_RDWR|O_CREAT,0640); if (lfp<0) exit(1); /* can not open */ if (lockf(lfp,F_TLOCK,0)<0) { cout << "Another instance of daemon is already running" << endl; exit(-1); /* can not lock */ } /* first instance continues */ if(getppid()==1) return; /* already a daemon */ i=fork(); if (i<0) exit(1); /* fork error */ if (i>0) exit(0); /* parent exits */ /* child (daemon) continues */ setsid(); /* obtain a new process group */ //for (i=getdtablesize();i>=0;--i) close(i); /* close all descriptors */ close(0); i=open("/dev/null",O_RDWR); if(dup(i) < 0) { log_message(LOG_FILE, "Redirecting standard input to /dev/null failed"); exit(-1); } if(freopen ("stdout.log","w",stdout) < 0) { log_message(LOG_FILE, "Redirecting standard output to stdout.log failed"); exit(-1); } if(freopen ("stderr.log","w",stderr) < 0) { log_message(LOG_FILE, "Redirecting standard error output to stderr.log failed"); exit(-1); } umask(022); /* set newly created file permissions */ sprintf(str,"%d\n",getpid()); if(write(lfp,str,strlen(str)) < 0) { log_message(LOG_FILE, "couldn't record pid to lockfile"); exit(-1); /* record pid to lockfile */ } signal(SIGCHLD,SIG_IGN); /* ignore child */ signal(SIGTSTP,SIG_IGN); /* ignore tty signals */ signal(SIGTTOU,SIG_IGN); signal(SIGTTIN,SIG_IGN); signal(SIGHUP,signal_handler); /* catch hangup signal */ signal(SIGTERM,signal_handler); /* catch kill signal */ } void setup(int argc, char* argv[]) { if(chdir(RUNNING_DIR) < 0) { cout << "Couldn't change directory to running dir: " << RUNNING_DIR; exit(-1); } /* change running directory */ char* config_file; if(argc > 0) config_file = argv[0]; else config_file = (char*)"daemon.config"; ifstream fin(config_file); if ( (fin.rdstate() & ifstream::failbit) != 0 ) { cerr << "Error while opening configuration file: " << config_file << "current running dir: " << RUNNING_DIR << endl; exit(-1); } fin.getline(gssimdir, 255); if ( (fin.rdstate() & (ifstream::failbit | ifstream::eofbit)) != 0 ) { cerr << "Error while reading gssim dir" << endl; exit(-1); } fin.getline(gssimexecfile, 255); if ( (fin.rdstate() & (ifstream::failbit | ifstream::eofbit)) != 0 ) { cerr << "Error while reading gssim exec file name" << endl;; exit(-1); } fin.getline(basedir, 255); if ( (fin.rdstate() & (ifstream::failbit | ifstream::eofbit)) != 0 ) { cerr << "Error while reading base watch directory name" << endl; exit(-1); } fin.close(); if(chdir(RUNNING_DIR) < 0) { cout << "Couldn't change directory to running dir: " << RUNNING_DIR; exit(-1); } /* change running directory */ signal(SIGINT, signal_handler); /*creating the INOTIFY instance*/ fd = inotify_init(); /*checking for error*/ if (fd < 0) { perror("inotify_init"); } wd = inotify_add_watch(fd, basedir, IN_CREATE | IN_CLOSE_WRITE); paths[wd] = basedir; strcpy(msg, "Directory "); strcat(msg, basedir); strcat(msg, " is added to watch list"); log_message(LOG_FILE, msg); } void monitor() { while (1) { int i = 0; length = read(fd, buffer, EVENT_BUF_LEN); if (length < 0) { log_message(LOG_FILE, "Severe error while monitoring occured (couldn't read event buffer)"); } while (i < length) { struct inotify_event *event = (struct inotify_event *) &buffer[i]; if (event->len) { if (event->mask & IN_CREATE) { if (event->mask & IN_ISDIR) { strcpy(msg, "New directory "); strcat(msg, event->name); strcat(msg, " created."); log_message(LOG_FILE, msg); char dir[255] = "\0"; strcat(dir, paths[event->wd]); strcat(dir, "/"); strcat(dir, event->name); wd = inotify_add_watch(fd, dir, IN_CREATE | IN_CLOSE_WRITE); strcpy(msg, "Directory "); strcat(msg, dir); strcat(msg, " is added to watch list"); log_message(LOG_FILE, msg); paths[wd] = dir; } } else if (event->mask & (IN_CLOSE_WRITE | IN_MOVED_TO)) { string name = event->name; char path[255]; strcpy(path, paths[event->wd]); strcpy(msg, "File "); strcat(msg, path); strcat(msg, "/"); strcat(msg, name.c_str()); strcat(msg, " writing is finished or file has just been moved."); log_message(LOG_FILE, msg); int index = name.rfind(".tar"); if ((index + 4) == (int)name.length()) { strcpy(msg, "Directory "); strcat(msg, paths[event->wd]); strcat(msg, "/"); strcat(msg, "is about to be erased from watch list"); log_message(LOG_FILE, msg); paths.erase(event->wd); inotify_rm_watch(fd, event->wd); log_message(LOG_FILE, "Directory erased from watch list"); int pid = fork(); if (pid == 0) { if(chdir(gssimdir) < 0) { strcpy(msg, "Could not access gssim directory: "); strcat(msg, gssimdir); log_message(LOG_FILE, msg); } char gssim[255] = "\0"; strcpy(gssim, gssimdir); strcat(gssim, "/"); strcat(gssim, gssimexecfile); strcat(path, "/"); strcat(path, name.c_str()); cout << gssim << endl << path << endl; execl(gssim, "gssim", path, NULL); } else { waitpid(pid, NULL, 0); log_message(LOG_FILE, "Triggered operation finished"); } } } } i += EVENT_SIZE + event->len; } } } int main(int argc, char* argv[]) { setup(argc, argv); daemonize(); cout << "log" << endl; cerr << "logerr" << endl; monitor(); }