//
// unix.c
//
//
//
//-UserX

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
/*
#if !defined(LOCK_EX) && !defined(LOCK_NB)
#include <fcntl.h>
#endif
*/
#include <string.h>
#include <stdio.h>

#include "misc/unix.h"
#include "base/logger.h"
#include "base/str.h"
#include "misc/global.h"
/**
@author UserX
@name unix
*/
//@{
/**
@return The number of processes SIGHUPped.
*/

int fdlock = 0;
char *lockfilename = NULL;

int unixSignalKin(int signum, char *lockfilepath, char *lockfileprefix) {
	//char *s;
	DIR *dir;
	struct dirent *de;
	int pid;
	int i = 0;
	if(lockfilepath == NULL) {
		return -1;
	}
	if(lockfileprefix == NULL) {
		return -1;
	}
	//todo: add checks for valid pathname
	//s = stringCopyMany(lockfilepath, lockfileprefix, NULL);
	dir = opendir(lockfilepath);
	//stringFree(s);
	if(dir == NULL) {
		LOGERROR(stringCopyMany("unixSighupKin: failed opendir(", lockfilepath, ")", 
			_("Unable to open lockfile directory!"), NULL));
		return -1;
	}
	//todo: revisit readdir might break if files are deleted while in use
	for(de = readdir(dir); de != NULL; de = readdir(dir)) {
		if(strncmp(lockfileprefix, de->d_name, strlen(lockfileprefix)) == 0) {
			/*
			s = stringCopyMany(lockfilepath, de->d_name, NULL);
			if(unlink(s) != 0) {
			*/
				sscanf(de->d_name + strlen(lockfileprefix), "%d", &pid);
				kill((pid_t) pid, signum);
				LOGDEBUG(stringCopyMany("unixSighupKin: signal pidlock(",de->d_name,")", 
					_("Sent signal to existing process."), NULL));
				i++;
			/*
			} else {
				LOGDEBUG(stringCopyMany("unixSighupKin: released pidlock(",de->d_name,")", 
					_("Released old lockfile."), NULL));
			}
			stringFree(s);
			*/
		}
	}
	closedir(dir);
	//todo: logging on error
	return i;
}

int unixAddLockFile(char *lockfilepath, char *lockfileprefix) {
	char *s;
	int fd;
	int i = 0;
/*
#if !defined(LOCK_EX) && !defined(LOCK_NB)
	struct flock fl;
#endif
*/
	if(lockfilepath == NULL) {
		return -1;
	}
	if(lockfileprefix == NULL) {
		return -1;
	}
	s = stringCopyMany(lockfilepath, lockfileprefix, NULL);
	s = stringJoinMany(s, intToString((int) getpid()), NULL);

	fd = open(s, O_CREAT | O_EXCL | S_IWUSR);
	if(fd == -1) {
		LOGERROR(stringCopyMany("unixAddLockFile: open lock file failed (", s, ")", 
			_("Error opening lockfile."), NULL))
		stringFree(s);
		return -1;
	}
	fdlock = fd;
	lockfilename = s;
	signal(SIGTERM, unixSignalTERM);
	signal(SIGINT, unixSignalTERM);
#if defined(LOCK_EX) && defined(LOCK_NB)
	i = flock(fd, LOCK_EX | LOCK_NB);
/*
#elif defined(F_WRLCK) && defined(F_SETLK)
	fl.l_type = F_WRLCK;
	i = fcntl(fd, F_SETLK, &fl);
*/
#else
	i = 0;
#endif

	if(i == -1) {
		LOGERROR(stringCopyMany("unixAddLockFile: locking of lock file failed (", s, ")", 
			_("Error locking lockfile."), NULL))
		//stringFree(s);
		return -1;
	}
	LOGMINOR(stringCopyMany("unixAddLockFile: locked lock file (", s, ")", 
		_("Successfully established a lockfile."), NULL))
	//stringFree(s);
	return fd;

}

void unixSignalHUP(int i) {
	reloadsettings = 1;
}

void unixSignalTERM(int i) {
	if(fdlock != 0) {
		close(fdlock);
	}
	if(lockfilename != NULL) {
		unlink(lockfilename);
	}
	exit(0);
}
//@}



syntax highlighted by Code2HTML, v. 0.9.1