Prevent more than one instance of tdekbdledsync from starting on a given X11 display

This resolves Bug 1601
pull/2/head
Timothy Pearson 11 years ago
parent bac7ea9a27
commit 4d8f3a663f

@ -33,6 +33,7 @@ License along with tdekbdledsync. If not, see http://www.gnu.org/licenses/.
#include <linux/vt.h> #include <linux/vt.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/uinput.h> #include <linux/uinput.h>
#include <sys/file.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/select.h> #include <sys/select.h>
@ -71,6 +72,9 @@ int keyboard_fds[MAX_KEYBOARDS];
Display* display = NULL; Display* display = NULL;
int lockfd = -1;
char lockFileName[256];
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// Useful function from Stack Overflow // Useful function from Stack Overflow
// http://stackoverflow.com/questions/874134/find-if-string-endswith-another-string-in-c // http://stackoverflow.com/questions/874134/find-if-string-endswith-another-string-in-c
@ -91,6 +95,34 @@ int str_ends_with(const char * str, const char * suffix) {
} }
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
// Useful function from Stack Overflow
// http://stackoverflow.com/questions/1599459/optimal-lock-file-method
// --------------------------------------------------------------------------------------
int tryGetLock(char const *lockName) {
mode_t m = umask( 0 );
int fd = open( lockName, O_RDWR|O_CREAT, 0666 );
umask( m );
if( fd >= 0 && flock( fd, LOCK_EX | LOCK_NB ) < 0 ) {
close( fd );
fd = -1;
}
return fd;
}
// --------------------------------------------------------------------------------------
// Useful function from Stack Overflow
// http://stackoverflow.com/questions/1599459/optimal-lock-file-method
// --------------------------------------------------------------------------------------
void releaseLock(int fd, char const *lockName) {
if( fd < 0 ) {
return;
}
remove( lockName );
close( fd );
}
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// Get the VT number X is running on // Get the VT number X is running on
// (code taken from GDM, daemon/getvt.c, GPLv2+) // (code taken from GDM, daemon/getvt.c, GPLv2+)
@ -254,6 +286,13 @@ int find_keyboards() {
return 0; return 0;
} }
void handle_sigterm(int signum) {
if (lockfd >= 0) {
releaseLock(lockfd, lockFileName);
}
exit(0);
}
int main() { int main() {
int current_keyboard; int current_keyboard;
char name[256] = "Unknown"; char name[256] = "Unknown";
@ -276,6 +315,12 @@ int main() {
int evBase; int evBase;
int errBase; int errBase;
// Register cleanup handlers
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = handle_sigterm;
sigaction(SIGTERM, &action, NULL);
// Open X11 display // Open X11 display
display = XOpenDisplay(NULL); display = XOpenDisplay(NULL);
if (!display) { if (!display) {
@ -283,13 +328,22 @@ int main() {
return -1; return -1;
} }
// Ensure only one process is running on a given display
sprintf(lockFileName, "/var/lock/tdekbdledsync-%s.lock", XDisplayString(display));
lockfd = tryGetLock(lockFileName);
if (lockfd < 0) {
printf ("[tdekbdledsync] Another instance of this program is already running on this X11 display!\n[tdekbdledsync] Lockfile detected at '%s'\n", lockFileName);
return -2;
}
// Set up Xkb extension // Set up Xkb extension
int i1, mn, mj; int i1, mn, mj;
mj = XkbMajorVersion; mj = XkbMajorVersion;
mn = XkbMinorVersion; mn = XkbMinorVersion;
if (!XkbQueryExtension(display, &i1, &evBase, &errBase, &mj, &mn)) { if (!XkbQueryExtension(display, &i1, &evBase, &errBase, &mj, &mn)) {
printf("[tdekbdledsync] Server doesn't support a compatible XKB\n"); printf("[tdekbdledsync] Server doesn't support a compatible XKB\n");
return -2; releaseLock(lockfd, lockFileName);
return -3;
} }
XkbSelectEvents(display, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask); XkbSelectEvents(display, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask);
@ -309,7 +363,8 @@ int main() {
udev = udev_new(); udev = udev_new();
if (!udev) { if (!udev) {
printf("[tdekbdledsync] Cannot connect to udev interface\n"); printf("[tdekbdledsync] Cannot connect to udev interface\n");
return -3; releaseLock(lockfd, lockFileName);
return -4;
} }
// Set up a udev monitor to monitor input devices // Set up a udev monitor to monitor input devices
@ -327,7 +382,8 @@ int main() {
find_keyboards(); find_keyboards();
if (keyboard_fd_num == 0) { if (keyboard_fd_num == 0) {
printf ("[tdekbdledsync] Could not find any usable keyboard(s)!\n"); printf ("[tdekbdledsync] Could not find any usable keyboard(s)!\n");
return -4; releaseLock(lockfd, lockFileName);
return -5;
} }
else { else {
fprintf(stderr, "[tdekbdledsync] Found %d keyboard(s)\n", keyboard_fd_num); fprintf(stderr, "[tdekbdledsync] Found %d keyboard(s)\n", keyboard_fd_num);
@ -342,14 +398,16 @@ int main() {
// Get current active VT // Get current active VT
if (ioctl(vt_fd, VT_GETSTATE, &vtstat)) { if (ioctl(vt_fd, VT_GETSTATE, &vtstat)) {
fprintf(stderr, "[tdekbdledsync] Unable to get current VT!\n"); fprintf(stderr, "[tdekbdledsync] Unable to get current VT!\n");
return -5; releaseLock(lockfd, lockFileName);
return -6;
} }
if (x11_vt_num == vtstat.v_active) { if (x11_vt_num == vtstat.v_active) {
// Get Virtual Core keyboard status // Get Virtual Core keyboard status
if (XkbGetIndicatorState(display, XkbUseCoreKbd, &states) != Success) { if (XkbGetIndicatorState(display, XkbUseCoreKbd, &states) != Success) {
fprintf(stderr, "[tdekbdledsync] Unable to query X11 Virtual Core keyboard!\n"); fprintf(stderr, "[tdekbdledsync] Unable to query X11 Virtual Core keyboard!\n");
return -6; releaseLock(lockfd, lockFileName);
return -7;
} }
XkbGetState(display, XkbUseCoreKbd, &state); XkbGetState(display, XkbUseCoreKbd, &state);
@ -440,5 +498,6 @@ int main() {
} }
} }
releaseLock(lockfd, lockFileName);
return 0; return 0;
} }

Loading…
Cancel
Save