diff options
Diffstat (limited to 'nslcd/hackers_watch.c')
-rw-r--r-- | nslcd/hackers_watch.c | 120 |
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); } } |