From 81cc2719beab0317b52764e8cf56afd8f56b0c89 Mon Sep 17 00:00:00 2001 From: Itay Grudev Date: Tue, 3 Mar 2020 01:22:54 +0000 Subject: [PATCH] v3.1.0a Added primaryUser() Closes #95 --- .gitignore | 14 ++++--- CHANGELOG.md | 5 +++ README.md | 8 ++++ examples/sending_arguments/main.cpp | 3 ++ singleapplication.cpp | 6 +++ singleapplication.h | 6 +++ singleapplication_p.cpp | 60 ++++++++++++++++++----------- singleapplication_p.h | 3 ++ 8 files changed, 77 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index c835f80..35533fe 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,11 @@ /examples/basic/basic /examples/calculator/calculator /examples/sending_arguments/sending_arguments -CMakeLists.txt.user -CMakeCache.txt -CMakeCache/* -CMakeFiles/* -Makefile -cmake_install.cmake +/**/CMakeLists.txt.user +/**/CMakeCache.txt +/**/CMakeCache/* +/**/CMakeFiles/* +/**/Makefile +/**/cmake_install.cmake +/**/*_autogen/ +libSingleApplication.a diff --git a/CHANGELOG.md b/CHANGELOG.md index 36f1e26..2eea70c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Changelog ========= +__3.1.0a__ +---------- + +* Added primaryUser() method that returns the user the primary instance is running as. + __3.0.19__ ---------- diff --git a/README.md b/README.md index fa60057..d3071eb 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,14 @@ qint64 SingleApplication::primaryPid() Returns the process ID (PID) of the primary instance. +--- + +```cpp +QString SingleApplication::primaryUser() +``` + +Returns the username the primary instance is running as. + ### Signals ```cpp diff --git a/examples/sending_arguments/main.cpp b/examples/sending_arguments/main.cpp index d90b250..a9d34dd 100755 --- a/examples/sending_arguments/main.cpp +++ b/examples/sending_arguments/main.cpp @@ -11,6 +11,9 @@ int main(int argc, char *argv[]) // If this is a secondary instance if( app.isSecondary() ) { app.sendMessage( app.arguments().join(' ').toUtf8() ); + qDebug() << "App already running."; + qDebug() << "Primary instance PID: " << app.primaryPid(); + qDebug() << "Primary instance user: " << app.primaryUser(); return 0; } else { QObject::connect( diff --git a/singleapplication.cpp b/singleapplication.cpp index 8ff8747..26e4ca2 100644 --- a/singleapplication.cpp +++ b/singleapplication.cpp @@ -172,6 +172,12 @@ qint64 SingleApplication::primaryPid() return d->primaryPid(); } +QString SingleApplication::primaryUser() +{ + Q_D(SingleApplication); + return d->primaryUser(); +} + bool SingleApplication::sendMessage( QByteArray message, int timeout ) { Q_D(SingleApplication); diff --git a/singleapplication.h b/singleapplication.h index cb50597..f91e3a2 100644 --- a/singleapplication.h +++ b/singleapplication.h @@ -112,6 +112,12 @@ public: */ qint64 primaryPid(); + /** + * @brief Returns the username of the user running the primary instance + * @returns {QString} + */ + QString primaryUser(); + /** * @brief Sends a message to the primary instance. Returns true on success. * @param {int} timeout - Timeout for connecting diff --git a/singleapplication_p.cpp b/singleapplication_p.cpp index 884fe63..8eb49ab 100644 --- a/singleapplication_p.cpp +++ b/singleapplication_p.cpp @@ -76,6 +76,7 @@ SingleApplicationPrivate::~SingleApplicationPrivate() delete server; inst->primary = false; inst->primaryPid = -1; + inst->primaryUser[0] = '\0'; inst->checksum = blockChecksum(); } memory->unlock(); @@ -83,6 +84,27 @@ SingleApplicationPrivate::~SingleApplicationPrivate() delete memory; } +QByteArray SingleApplicationPrivate::getUsername(){ +#ifdef Q_OS_WIN + wchar_t username[UNLEN + 1]; + // Specifies size of the buffer on input + DWORD usernameLength = UNLEN + 1; + if( GetUserNameW( username, &usernameLength ) ) + return QString::fromWCharArray( username ).toUtf8(); + return qgetenv( "USERNAME" ); +#endif +#ifdef Q_OS_UNIX + QByteArray username; + uid_t uid = geteuid(); + struct passwd *pw = getpwuid( uid ); + if( pw ) + username = pw->pw_name; + if( username.isEmpty() ) + username = qgetenv( "USER" ); + return username; +#endif +} + void SingleApplicationPrivate::genBlockServerName() { QCryptographicHash appData( QCryptographicHash::Sha256 ); @@ -105,28 +127,7 @@ void SingleApplicationPrivate::genBlockServerName() // User level block requires a user specific data in the hash if( options & SingleApplication::Mode::User ) { -#ifdef Q_OS_WIN - wchar_t username [ UNLEN + 1 ]; - // Specifies size of the buffer on input - DWORD usernameLength = UNLEN + 1; - if( GetUserNameW( username, &usernameLength ) ) { - appData.addData( QString::fromWCharArray(username).toUtf8() ); - } else { - appData.addData( qgetenv("USERNAME") ); - } -#endif -#ifdef Q_OS_UNIX - QByteArray username; - uid_t uid = geteuid(); - struct passwd *pw = getpwuid(uid); - if( pw ) { - username = pw->pw_name; - } - if( username.isEmpty() ) { - username = qgetenv("USER"); - } - appData.addData(username); -#endif + appData.addData( getUsername() ); } // Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with @@ -140,6 +141,7 @@ void SingleApplicationPrivate::initializeMemoryBlock() inst->primary = false; inst->secondary = 0; inst->primaryPid = -1; + inst->primaryUser[0] = '\0'; inst->checksum = blockChecksum(); } @@ -173,6 +175,8 @@ void SingleApplicationPrivate::startPrimary() inst->primary = true; inst->primaryPid = q->applicationPid(); + strncpy( inst->primaryUser, getUsername().data(), 127 ); + inst->primaryUser[127] = '\0'; inst->checksum = blockChecksum(); instanceNumber = 0; @@ -257,6 +261,18 @@ qint64 SingleApplicationPrivate::primaryPid() return pid; } +QString SingleApplicationPrivate::primaryUser() +{ + QByteArray username; + + memory->lock(); + InstancesInfo* inst = static_cast( memory->data() ); + username = inst->primaryUser; + memory->unlock(); + + return QString::fromUtf8( username ); +} + /** * @brief Executed when a connection has been made to the LocalServer */ diff --git a/singleapplication_p.h b/singleapplication_p.h index e2c361f..5161411 100644 --- a/singleapplication_p.h +++ b/singleapplication_p.h @@ -42,6 +42,7 @@ struct InstancesInfo { quint32 secondary; qint64 primaryPid; quint16 checksum; + char primaryUser[128]; }; struct ConnectionInfo { @@ -71,6 +72,7 @@ public: SingleApplicationPrivate( SingleApplication *q_ptr ); ~SingleApplicationPrivate(); + QByteArray getUsername(); void genBlockServerName(); void initializeMemoryBlock(); void startPrimary(); @@ -78,6 +80,7 @@ public: void connectToPrimary(int msecs, ConnectionType connectionType ); quint16 blockChecksum(); qint64 primaryPid(); + QString primaryUser(); void readInitMessageHeader(QLocalSocket *socket); void readInitMessageBody(QLocalSocket *socket);