mirror of
https://github.com/znc/znc.git
synced 2026-05-02 03:22:33 +02:00
Changed from checking pidfile to locking the config
git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@177 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
192
Utils.h
192
Utils.h
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -19,8 +21,7 @@ using std::map;
|
||||
|
||||
static const char g_HexDigits[] = "0123456789abcdef";
|
||||
|
||||
class CUtils
|
||||
{
|
||||
class CUtils {
|
||||
public:
|
||||
CUtils();
|
||||
virtual ~CUtils();
|
||||
@@ -56,14 +57,133 @@ public:
|
||||
static string Token(const string& s, unsigned int uPos, bool bRest = false, char cSep = ' ');
|
||||
static string Ellipsize(const string& s, unsigned int uLen);
|
||||
static bool wildcmp(const string& sWild, const string& sString);
|
||||
|
||||
static unsigned long long GetMillTime() {
|
||||
struct timeval tv;
|
||||
unsigned long long iTime = 0;
|
||||
gettimeofday(&tv, NULL);
|
||||
iTime = (unsigned long long) tv.tv_sec * 1000;
|
||||
iTime += ((unsigned long long) tv.tv_usec / 1000);
|
||||
return iTime;
|
||||
}
|
||||
#ifdef HAVE_LIBSSL
|
||||
static void GenerateCert( FILE *pOut, bool bEncPrivKey = false );
|
||||
static void GenerateCert(FILE *pOut, bool bEncPrivKey = false);
|
||||
#endif /* HAVE_LIBSSL */
|
||||
|
||||
|
||||
private:
|
||||
protected:
|
||||
};
|
||||
|
||||
class CLockFile {
|
||||
public:
|
||||
CLockFile() {
|
||||
m_bCreated = false;
|
||||
m_fd = 0;
|
||||
m_pid = 0;
|
||||
}
|
||||
|
||||
CLockFile(const string& sFile) {
|
||||
Open(sFile);
|
||||
}
|
||||
|
||||
virtual ~CLockFile() {
|
||||
if (getpid() == m_pid) {
|
||||
if (m_fd > -1) {
|
||||
UnLock();
|
||||
close(m_fd);
|
||||
if (m_bCreated) {
|
||||
unlink(m_sFileName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Open(const string& sFile) {
|
||||
m_fd = open(sFile.c_str(), O_RDONLY);
|
||||
m_bCreated = false;
|
||||
|
||||
if (m_fd == -1) {
|
||||
// i must create the file then
|
||||
m_fd = open(sFile.c_str(), O_RDWR|O_CREAT, 0644);
|
||||
m_bCreated = true;
|
||||
}
|
||||
|
||||
m_pid = getpid(); // for destructor
|
||||
m_sFileName = sFile;
|
||||
}
|
||||
|
||||
//! timeout in milliseconds
|
||||
bool TryExLock(const string& sLockFile, unsigned long long iTimeout = 0) {
|
||||
Open(sLockFile);
|
||||
return TryExLock(iTimeout);
|
||||
}
|
||||
|
||||
bool TryExLock(unsigned long long iTimeout = 0) {
|
||||
if (iTimeout == 0) {
|
||||
return Lock(LOCK_EX|LOCK_NB);
|
||||
}
|
||||
|
||||
unsigned long long iNow = CUtils::GetMillTime();
|
||||
|
||||
while(true) {
|
||||
if (Lock(LOCK_EX|LOCK_NB)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((CUtils::GetMillTime() - iNow) > iTimeout) {
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
bool TryShLock(unsigned long long iTimeout = 0) {
|
||||
if (iTimeout == 0) {
|
||||
return(Lock(LOCK_SH|LOCK_NB));
|
||||
}
|
||||
|
||||
unsigned long long iNow = CUtils::GetMillTime();
|
||||
|
||||
while(true) {
|
||||
if (Lock(LOCK_SH|LOCK_NB)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((CUtils::GetMillTime() - iNow) > iTimeout) {
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LockEx() { return Lock(LOCK_EX); }
|
||||
bool LockSh() { return Lock(LOCK_SH); }
|
||||
bool UnLock() { return Lock(LOCK_UN); }
|
||||
|
||||
private:
|
||||
bool Lock(int iOperation) {
|
||||
if (m_fd == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::flock(m_fd, iOperation) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int m_fd;
|
||||
int m_pid;
|
||||
bool m_bCreated;
|
||||
string m_sFileName;
|
||||
};
|
||||
|
||||
class CException {
|
||||
public:
|
||||
@@ -106,8 +226,7 @@ public:
|
||||
CFile(const string& sLongName);
|
||||
virtual ~CFile();
|
||||
|
||||
enum EFileTypes
|
||||
{
|
||||
enum EFileTypes {
|
||||
FT_REGULAR,
|
||||
FT_DIRECTORY,
|
||||
FT_CHARACTER,
|
||||
@@ -117,26 +236,26 @@ public:
|
||||
FT_SOCK
|
||||
};
|
||||
|
||||
static bool IsReg( const string& sLongName, bool bUseLstat = false );
|
||||
static bool IsDir( const string& sLongName, bool bUseLstat = false );
|
||||
static bool IsChr( const string& sLongName, bool bUseLstat = false );
|
||||
static bool IsBlk( const string& sLongName, bool bUseLstat = false );
|
||||
static bool IsFifo( const string& sLongName, bool bUseLstat = false );
|
||||
static bool IsLnk( const string& sLongName, bool bUseLstat = true );
|
||||
static bool IsSock( const string& sLongName, bool bUseLstat = false );
|
||||
static bool IsReg(const string& sLongName, bool bUseLstat = false);
|
||||
static bool IsDir(const string& sLongName, bool bUseLstat = false);
|
||||
static bool IsChr(const string& sLongName, bool bUseLstat = false);
|
||||
static bool IsBlk(const string& sLongName, bool bUseLstat = false);
|
||||
static bool IsFifo(const string& sLongName, bool bUseLstat = false);
|
||||
static bool IsLnk(const string& sLongName, bool bUseLstat = true);
|
||||
static bool IsSock(const string& sLongName, bool bUseLstat = false);
|
||||
|
||||
bool IsReg( bool bUseLstat = false );
|
||||
bool IsDir( bool bUseLstat = false );
|
||||
bool IsChr( bool bUseLstat = false );
|
||||
bool IsBlk( bool bUseLstat = false );
|
||||
bool IsFifo( bool bUseLstat = false );
|
||||
bool IsLnk( bool bUseLstat = true );
|
||||
bool IsSock( bool bUseLstat = false );
|
||||
bool IsReg(bool bUseLstat = false);
|
||||
bool IsDir(bool bUseLstat = false);
|
||||
bool IsChr(bool bUseLstat = false);
|
||||
bool IsBlk(bool bUseLstat = false);
|
||||
bool IsFifo(bool bUseLstat = false);
|
||||
bool IsLnk(bool bUseLstat = true);
|
||||
bool IsSock(bool bUseLstat = false);
|
||||
|
||||
bool access( int mode );
|
||||
bool access(int mode);
|
||||
|
||||
// for gettin file types, using fstat instead
|
||||
static bool FType( const string sFileName, EFileTypes eType, bool bUseLstat = false );
|
||||
static bool FType(const string sFileName, EFileTypes eType, bool bUseLstat = false);
|
||||
|
||||
enum EFileAttr {
|
||||
FA_Name,
|
||||
@@ -178,16 +297,16 @@ public:
|
||||
bool Chmod(mode_t mode);
|
||||
static bool Chmod(const string& sFile, mode_t mode);
|
||||
bool Seek(unsigned long uPos);
|
||||
bool Open( int iFlags, mode_t iMode = 0644 );
|
||||
int Read( char *pszBuffer, int iBytes );
|
||||
bool ReadLine( string & sData );
|
||||
int Write( const char *pszBuffer, u_int iBytes );
|
||||
int Write( const string & sData );
|
||||
bool Open(int iFlags, mode_t iMode = 0644);
|
||||
int Read(char *pszBuffer, int iBytes);
|
||||
bool ReadLine(string & sData);
|
||||
int Write(const char *pszBuffer, u_int iBytes);
|
||||
int Write(const string & sData);
|
||||
void Close();
|
||||
|
||||
string GetLongName() const;
|
||||
string GetShortName() const;
|
||||
void SetFD( int iFD );
|
||||
void SetFD(int iFD);
|
||||
|
||||
private:
|
||||
string m_sBuffer;
|
||||
@@ -203,8 +322,7 @@ protected:
|
||||
#include <openssl/blowfish.h>
|
||||
#include <openssl/md5.h>
|
||||
//! does Blowfish w/64 bit feedback, no padding
|
||||
class CBlowfish
|
||||
{
|
||||
class CBlowfish {
|
||||
public:
|
||||
/**
|
||||
* @sPassword key to encrypt with
|
||||
@@ -217,7 +335,7 @@ public:
|
||||
//! output must be freed
|
||||
static unsigned char *MD5(const unsigned char *input, u_int ilen);
|
||||
|
||||
//! returns an md5 of the string ( not hex encoded )
|
||||
//! returns an md5 of the string (not hex encoded)
|
||||
static string MD5(const string & sInput, bool bHexEncode = false);
|
||||
|
||||
//! output must be the same size as input
|
||||
@@ -241,9 +359,9 @@ inline bool ReadFile(const string & sFilename, string & sLine) {
|
||||
int bytes;
|
||||
// clear ourselves out
|
||||
sLine.clear();
|
||||
|
||||
|
||||
FILE *f = fopen(sFilename.c_str(), "r");
|
||||
|
||||
|
||||
if (!f) {
|
||||
return false;
|
||||
}
|
||||
@@ -251,12 +369,12 @@ inline bool ReadFile(const string & sFilename, string & sLine) {
|
||||
while((bytes = fread(inbuff, sizeof(char), RF_BUFF, f)) > 0) {
|
||||
sLine.append(inbuff, bytes);
|
||||
}
|
||||
|
||||
|
||||
fclose(f);
|
||||
if (bytes < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -269,7 +387,7 @@ inline bool WriteFile(const string & sFilename, const string & sData) {
|
||||
int iRet = fwrite(sData.data(), sizeof(char), sData.length(), f);
|
||||
|
||||
fclose(f);
|
||||
|
||||
|
||||
if (iRet <= 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -312,7 +430,7 @@ inline string Upper(const string & sLine) {
|
||||
for(u_int a = 0; a < sLine.length(); a++) {
|
||||
sRet += toupper(sLine[a]);
|
||||
}
|
||||
|
||||
|
||||
return sRet;
|
||||
}
|
||||
|
||||
|
||||
53
znc.cpp
53
znc.cpp
@@ -126,46 +126,6 @@ void CZNC::ReleaseISpoof() {
|
||||
m_bISpoofLocked = false;
|
||||
}
|
||||
|
||||
bool CZNC::SetPidFile(const string& sFile) {
|
||||
CUtils::PrintAction("Checking PidFile [" + sFile + "]");
|
||||
|
||||
if (!sFile.empty() && sFile[0] != '/') {
|
||||
m_sPidFile = GetZNCPath() + "/" + sFile;
|
||||
} else {
|
||||
m_sPidFile = sFile;
|
||||
}
|
||||
|
||||
if (!m_sPidFile.empty()) {
|
||||
unsigned int uPid = 0;
|
||||
CFile File(m_sPidFile);
|
||||
|
||||
if (File.Open(O_RDONLY)) {
|
||||
string sPid;
|
||||
|
||||
if (File.ReadLine(sPid)) {
|
||||
uPid = atoi(sPid.c_str());
|
||||
|
||||
if (uPid > 0 && kill(uPid, 0) == 0) {
|
||||
CUtils::PrintStatus(false, "ZNC already running [pid: " + CUtils::ToString(uPid) + "]");
|
||||
File.Close();
|
||||
|
||||
return false;
|
||||
} else {
|
||||
CUtils::PrintStatus(true, "Stale pid, relaunching");
|
||||
File.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
File.Close();
|
||||
}
|
||||
}
|
||||
|
||||
CUtils::PrintStatus(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CZNC::WritePidFile(int iPid) {
|
||||
if (!m_sPidFile.empty()) {
|
||||
CFile File(m_sPidFile);
|
||||
@@ -270,6 +230,11 @@ bool CZNC::ParseConfig(const string& sConfigFile) {
|
||||
|
||||
CUtils::PrintAction("Opening Config [" + sFilePath + "]");
|
||||
|
||||
if (!m_LockFile.TryExLock(sFilePath, 50)) {
|
||||
CUtils::PrintStatus(false, "ZNC is already running on this config.");
|
||||
return false;
|
||||
}
|
||||
|
||||
CFile File(sFilePath);
|
||||
|
||||
if (!File.Open(O_RDONLY)) {
|
||||
@@ -526,10 +491,10 @@ bool CZNC::ParseConfig(const string& sConfigFile) {
|
||||
m_sISpoofFile = sValue;
|
||||
continue;
|
||||
} else if (strcasecmp(sName.c_str(), "PidFile") == 0) {
|
||||
if (!sValue.empty()) {
|
||||
if (!SetPidFile(sValue)) {
|
||||
return false;
|
||||
}
|
||||
if (!sValue.empty() && sValue[0] != '/') {
|
||||
m_sPidFile = GetZNCPath() + "/" + sValue;
|
||||
} else {
|
||||
m_sPidFile = sValue;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
2
znc.h
2
znc.h
@@ -16,7 +16,6 @@ public:
|
||||
void DeleteUsers();
|
||||
int Loop();
|
||||
void ReleaseISpoof();
|
||||
bool SetPidFile(const string& sFile);
|
||||
bool WritePidFile(int iPid);
|
||||
CUser* GetUser(const string& sUser);
|
||||
Csock* FindSockByName(const string& sSockName);
|
||||
@@ -67,6 +66,7 @@ protected:
|
||||
string m_sISpoofFile;
|
||||
string m_sOrigISpoof;
|
||||
string m_sPidFile;
|
||||
CLockFile m_LockFile;
|
||||
bool m_bISpoofLocked;
|
||||
bool m_bSSL;
|
||||
map<string,CUser*>::iterator m_itUserIter; // This needs to be reset to m_msUsers.begin() if anything is added or removed to the map
|
||||
|
||||
Reference in New Issue
Block a user