[ekg2-commit] ekg2: protocol.c (HEAD) sessions.c (HEAD) sessions.h (HEAD) stuff.c (HEAD) stuff.h (HEAD) themes.c (HEAD) vars.c (HEAD) [peres]
CVS commit
cvs w toxygen.net
Wto, 1 Maj 2007, 16:09:11 CEST
Module name: ekg2
Changes by: peres 2007-05-01 16:09:08
Modified files:
protocol.c sessions.c sessions.h stuff.c stuff.h themes.c vars.c
Log message:
Implementing session-locking, to avoid connecting to the same session more
than one copy of EKG2 simultaneously. With special dedication to Greyer.
It is controlled by var session_locks. Allows two types of locking. Simpler
and more portable (2) just creates file on locking, and unlinks it on unlock.
If file exists before locking, locking fails and connect should be aborted.
The default one (1) uses additionally flock() on created file. The main
advantage of this is that if EKG2 dies, lock will die too, and we won't have
to remove it ,,by hand'' (i.e. using /session --unlock).
XXX: Do we need to check if flock() is available?
Index: protocol.c
===================================================================
RCS file: /home/cvs/ekg2/ekg/protocol.c,v
diff -d -u -r1.123 -r1.124
--- protocol.c 3 Apr 2007 13:22:29 -0000 1.123
+++ protocol.c 1 May 2007 14:09:07 -0000 1.124
@@ -159,6 +159,7 @@
s->last_conn = time(NULL);
s->connected = 0;
/* XXX notify ui */
+ command_exec(NULL, s, "/session --unlock", 1);
}
switch (type) {
Index: sessions.c
===================================================================
RCS file: /home/cvs/ekg2/ekg/sessions.c,v
diff -d -u -r1.121 -r1.122
--- sessions.c 9 Apr 2007 21:28:41 -0000 1.121
+++ sessions.c 1 May 2007 14:09:07 -0000 1.122
@@ -25,6 +25,12 @@
#include <string.h>
#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
#include "debug.h"
#include "dynstuff.h"
#include "sessions.h"
@@ -1234,6 +1240,85 @@
return -1;
}
+ if (match_arg(params[0], 'L', "lock", 2)) {
+ int fd;
+ const char *path;
+ char *tmp;
+ session_t *s;
+
+ if (params[1]) {
+ if (!(s = session_find(params[1]))) {
+ printq("session_doesnt_exist", params[1]);
+ return -1;
+ }
+ } else
+ s = session;
+ if (!config_session_locks)
+ return 0;
+ if (config_session_locks == 1 && session->lock_fd) {
+ print("session_locked", session_name(session));
+ return -1;
+ }
+
+ path = prepare_path((tmp = saprintf("%s%s", session_uid_get(session), "-lock")), 1);
+ xfree(tmp);
+ fd = open(path,
+ O_CREAT|O_WRONLY
+ | (config_session_locks != 1
+ ? O_EXCL /* if we don't use flock(), we just take care of file's existence */
+ : O_TRUNC
+ | O_NONBLOCK /* if someone's set up shitpipe for us */
+ ), S_IWUSR);
+
+ if (fd == -1) {
+ if (errno == EEXIST) {
+ print("session_locked", session_name(session));
+ return -1;
+ } else if (errno != ENXIO) {
+ /* XXX, be more loud? */
+ debug_error("session_command(), lock's open() failed with errno=%d\n", errno);
+ return 0;
+ }
+ }
+
+ if (config_session_locks == 1) {
+ if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
+ if (errno == EWOULDBLOCK) {
+ print("session_locked", session_name(session));
+ return -1;
+ } else {
+ debug_error("session_command(), lock's flock() failed with errno=%d\n", errno);
+ close(fd); /* if we can't lock, we don't need fd */
+ return 0;
+ }
+ }
+ session->lock_fd = fd;
+ } else
+ close(fd);
+
+ return 0;
+ }
+
+ if (match_arg(params[0], 'u', "unlock", 3)) {
+ int fd;
+ const char *path;
+ char *tmp;
+
+ if (!config_session_locks)
+ return 0;
+
+ if (config_session_locks == 1 && (fd = session->lock_fd)) {
+ flock(fd, LOCK_UN);
+ close(fd);
+ session->lock_fd = 0;
+ }
+
+ path = prepare_path((tmp = saprintf("%s%s", session_uid_get(session), "-lock")), 0);
+ xfree(tmp);
+ unlink(path);
+ return 0;
+ }
+
if ((s = session_find(params[0]))) {
int status;
char *tmp;
Index: sessions.h
===================================================================
RCS file: /home/cvs/ekg2/ekg/sessions.h,v
diff -d -u -r1.38 -r1.39
--- sessions.h 1 May 2007 11:57:22 -0000 1.38
+++ sessions.h 1 May 2007 14:09:07 -0000 1.39
@@ -59,6 +59,8 @@
/* new auto-away */
int laststatus; /**< user's status before going into autoaway */
char *lastdescr; /**< user's description before going into autoaway */
+
+ int lock_fd; /**< fd used for session locking */
} session_t;
#ifndef EKG2_WIN32_NOFUNCTION
Index: stuff.c
===================================================================
RCS file: /home/cvs/ekg2/ekg/stuff.c,v
diff -d -u -r1.186 -r1.187
--- stuff.c 1 May 2007 11:37:06 -0000 1.186
+++ stuff.c 1 May 2007 14:09:07 -0000 1.187
@@ -167,6 +167,7 @@
int config_lastlog_display_all = 0;
int config_version = 0;
char *config_exit_exec = NULL;
+int config_session_locks = 1; /* flock() by default */
char *last_search_first_name = NULL;
char *last_search_last_name = NULL;
Index: stuff.h
===================================================================
RCS file: /home/cvs/ekg2/ekg/stuff.h,v
diff -d -u -r1.98 -r1.99
--- stuff.h 1 May 2007 11:37:06 -0000 1.98
+++ stuff.h 1 May 2007 14:09:07 -0000 1.99
@@ -234,6 +234,7 @@
extern char *config_dcc_dir;
extern int config_version;
extern char *config_exit_exec;
+extern int config_session_locks;
extern char *home_dir;
extern char *config_dir;
Index: themes.c
===================================================================
RCS file: /home/cvs/ekg2/ekg/themes.c,v
diff -d -u -r1.175 -r1.176
--- themes.c 23 Apr 2007 20:10:24 -0000 1.175
+++ themes.c 1 May 2007 14:09:07 -0000 1.176
@@ -1859,6 +1859,7 @@
format_add("session_format_alias", "%T%1%n/%2", 1);
format_add("session_cannot_change", _("%! Can't change session in query window%n\n"), 1);
format_add("session_password_changed", _("%> %|(%1) Looks like you're changing password in connected session. This does only set password on the client-side. If you want you change your account password, please use dedicated function (e.g. /passwd)."), 1);
+ format_add("session_locked", _("%! %|Session %T%1%n is currently locked. If there aren't any other copy of EKG2 using it, please call:\n\t%c/session --unlock %1%n\nto unlock it.\n"), 1);
format_add("metacontact_list", "%> %T%1%n", 1);
format_add("metacontact_list_empty", "%! Metacontact list is empty\n", 1);
Index: vars.c
===================================================================
RCS file: /home/cvs/ekg2/ekg/vars.c,v
diff -d -u -r1.90 -r1.91
--- vars.c 1 May 2007 11:37:06 -0000 1.90
+++ vars.c 1 May 2007 14:09:08 -0000 1.91
@@ -130,6 +130,7 @@
variable_add(NULL, ("save_password"), VAR_BOOL, 1, &config_save_password, NULL, NULL, NULL);
variable_add(NULL, ("save_quit"), VAR_INT, 1, &config_save_quit, NULL, NULL, NULL);
variable_add(NULL, ("session_default"), VAR_STR, 2, &config_session_default, NULL, NULL, NULL);
+ variable_add(NULL, ("session_locks"), VAR_INT, 1, &config_session_locks, NULL, variable_map(3, 0, 0, "off", 1, 2, "flock", 2, 1, "file"), NULL);
variable_add(NULL, ("sessions_save"), VAR_BOOL, 1, &config_sessions_save, NULL, NULL, NULL);
variable_add(NULL, ("slash_messages"), VAR_BOOL, 1, &config_slash_messages, NULL, NULL, NULL);
variable_add(NULL, ("sort_windows"), VAR_BOOL, 1, &config_sort_windows, NULL, NULL, NULL);
Więcej informacji o liście dyskusyjnej ekg2-commit