summaryrefslogtreecommitdiff
path: root/nslcd/hackers_watch.c
diff options
context:
space:
mode:
Diffstat (limited to 'nslcd/hackers_watch.c')
-rw-r--r--nslcd/hackers_watch.c120
1 files changed, 88 insertions, 32 deletions
diff --git a/nslcd/hackers_watch.c b/nslcd/hackers_watch.c
index 7289c59..e2222fc 100644
--- a/nslcd/hackers_watch.c
+++ b/nslcd/hackers_watch.c
@@ -26,6 +26,7 @@
#include "common/inotify_helpers.h"
#include "hackers_parse.h"
#include "hackers_watch.h"
+#include "log.h"
#define EVENT_FILE_IS(event, str) \
(((event)->len == sizeof(str)) && (strcmp((event)->name, str) == 0))
@@ -44,17 +45,6 @@
} \
} while(0)
-#define REALLOC(ptr, size) \
- (__extension__ ({ \
- errno = 0; \
- void *ret = realloc(ptr, size); \
- if (ret == (ptr)) { \
- error(0, errno, "could not (re)allocate memory"); \
- goto error; \
- }; \
- ret; \
- }))
-
#define WATCH_HOMEDIR(session, i) \
do { \
session->in_user_wds[i] = \
@@ -64,18 +54,85 @@
if (session->in_user_wds[i] < 0) { \
error(0, errno, "could not watch: %s", \
session->users[i].pw_dir); \
- goto error; \
+ /* don't goto error, it OK here */ \
} \
} while(0)
+struct session *
+hackers_session_allocate() {
+ int err = 0;
+ struct session *sess;
+ sess = MALLOC(sizeof(struct session));
+ if ((err = pthread_rwlock_init(&(sess->lock), NULL)) != 0) {
+ error(0, err, "could not initialize session rwlock");
+ goto error;
+ }
+ sess->cnt = 0;
+ sess->users = NULL;
+ sess->yamldir = NULL;
+ sess->in_user_wds = NULL;
+ sess->in_fd = -1;
+ sess->in_wd_home = -1;
+ sess->in_wd_yaml = -1;
+ return sess;
+ error:
+ return NULL;
+}
+
+static
+int
+hackers_session_resize(struct session *sess, size_t num_users) {
+ log_log(LOG_DEBUG, "resizing session to %zu users", num_users);
+
+ if (num_users <= sess->cnt)
+ return 0;
+
+ sess->users =
+ REALLOC(sess->users , num_users * sizeof(sess->users[0]));
+ sess->in_user_wds =
+ REALLOC(sess->in_user_wds, num_users * sizeof(sess->in_user_wds[0]));
+
+ for (size_t i = sess->cnt; i < num_users; i++) {
+ ZERO(sess->users[i]);
+ sess->users[i].pw_uid = UID_INVALID;
+ sess->in_user_wds[i] = -1;
+ }
+ sess->cnt = num_users;
+
+ return 0;
+ error:
+ return -1;
+}
+
+/* does NOT mess with the lock */
+static
+void
+hackers_session_close(struct session *sess) {
+ log_log(LOG_DEBUG, "closing session");
+
+ for (size_t i = 0; i < sess->cnt; i++) {
+ PASSWD_FREE(sess->users[i]);
+ }
+ free(sess->users); sess->users = NULL;
+ sess->cnt = 0;
+
+ free(sess->yamldir); sess->yamldir = NULL;
+ free(sess->in_user_wds); sess->in_user_wds = NULL;
+ close(sess->in_fd); sess->in_fd = -1;
+ sess->in_wd_home = -1;
+ sess->in_wd_yaml = -1;
+}
+
int
-hackers_init(const char *yamldir, struct session *sess) {
+hackers_session_open(struct session *sess, const char *yamldir) {
+ log_log(LOG_DEBUG, "opening session at `%s'", yamldir);
char *glob_pattern;
glob_t glob_results;
char *filename;
+ hackers_session_close(sess);
ASSERT((sess->yamldir = strdup(yamldir)) != NULL);
- ASSERT((errno = pthread_rwlock_init(&(sess->lock), NULL)) >= 0);
+
ASSERT((sess->in_fd = inotify_init()) >= 0);
ASSERT((sess->in_wd_yaml = inotify_add_watch(sess->in_fd, yamldir, EVENT_CHILD_ANY)) >= 0);
ASSERT((sess->in_wd_home = inotify_add_watch(sess->in_fd, "/home" , EVENT_CHILD_ADD)) >= 0);
@@ -83,16 +140,16 @@ hackers_init(const char *yamldir, struct session *sess) {
ASSERT(asprintf(&glob_pattern, "%s/*.yml", yamldir) > 0);
ASSERT(glob(glob_pattern, 0, NULL, &glob_results) == 0);
free(glob_pattern);
-
- sess->cnt = glob_results.gl_pathc - glob_results.gl_offs;
- ASSERT((sess->users = calloc(sess->cnt, sizeof(struct passwd))) != NULL);
- ASSERT((sess->in_user_wds = calloc(sess->cnt, sizeof(int))) != NULL);
+ ASSERT(hackers_session_resize(sess, glob_results.gl_pathc - glob_results.gl_offs)==0);
for (size_t i = 0; i < sess->cnt; i++) {
filename = glob_results.gl_pathv[glob_results.gl_offs+i];
+ log_log(LOG_DEBUG, "loading yaml file: %s", filename);
if (load_user_yaml(filename, &(sess->users[i]))==0) {
+ log_log(LOG_DEBUG, "... and watching homedir");
WATCH_HOMEDIR(sess, i);
} else {
+ log_log(LOG_DEBUG, "... error");
sess->users[i].pw_uid = UID_INVALID;
sess->in_user_wds[i] = -1;
}
@@ -101,7 +158,9 @@ hackers_init(const char *yamldir, struct session *sess) {
globfree(&glob_results);
return 0;
+
error:
+ hackers_session_close(sess);
return -1;
}
@@ -121,20 +180,17 @@ worker_watch_homedirs(struct session *sess) {
}
}
pthread_rwlock_unlock(&(sess->lock));
- return;
- error:
- exit(1);
}
static
-void
+int
worker_handle_add_yaml(struct session *sess, struct passwd *newdata) {
/* We have to first see if this is for an existing UID, then
* if it's not, we need to find an empty slot, potentially
* realloc()ing the array.
*/
- pthread_rwlock_wrlock(&(sess->lock));
ssize_t spot = -1;
+ pthread_rwlock_wrlock(&(sess->lock));
for (size_t i = 0; i < sess->cnt; i++) {
if (spot < 0 && sess->users[i].pw_uid == UID_INVALID) {
spot = i;
@@ -146,18 +202,17 @@ worker_handle_add_yaml(struct session *sess, struct passwd *newdata) {
}
if (spot < 0) {
/* must grow the array */
- spot = sess->cnt++;
- sess->users = REALLOC(sess->users , sess->cnt * sizeof(struct passwd));
- sess->in_user_wds = REALLOC(sess->in_user_wds, sess->cnt * sizeof(int));
- ZERO(sess->users[spot]);
+ if (hackers_session_resize(sess, sess->cnt+1) != 0)
+ goto error;
} else if (sess->users[spot].pw_uid != UID_INVALID) {
PASSWD_FREE(sess->users[spot]);
}
sess->users[spot] = *newdata;
pthread_rwlock_unlock(&(sess->lock));
- return;
+ return 0;
error:
- exit(1);
+ pthread_rwlock_unlock(&(sess->lock));
+ return -1;
}
static
@@ -175,7 +230,7 @@ worker_handle_del_yaml(struct session *sess, uid_t uid) {
}
int
-hackers_worker(struct session *sess) {
+hackers_session_worker(struct session *sess) {
if (chdir(sess->yamldir) < 0)
return -1;
for (INOTIFY_ITERATOR(sess->in_fd, event)) {
@@ -185,7 +240,8 @@ hackers_worker(struct session *sess) {
struct passwd user; ZERO(user);
if (load_user_yaml(event->name, &user)==0) {
/* User added/updated */
- worker_handle_add_yaml(sess, &user);
+ if (worker_handle_add_yaml(sess, &user) !=0)
+ return -1;
} else if (user.pw_uid != UID_INVALID) {
/* User became invalid */
worker_handle_del_yaml(sess,
@@ -193,7 +249,7 @@ hackers_worker(struct session *sess) {
}
} else if (event->mask & EVENT_CHILD_DEL) {
uid_t uid = filename2uid(event->name);
- if (uid > 0) {
+ if (uid != UID_INVALID) {
worker_handle_del_yaml(sess, uid);
}
}