#include #include #include /* Directory information. */ #include #include /* for rand() */ #include #include #include "global.h" #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_authenticate.h" #include "manhat-lib/shared_super_util.h" #include "manhat-lib/shared_course_search.h" /* for GROUP_DESCRIPTION_FNAME */ #include "manhat-lib/shared_time.h" #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_super_menu.h" HDF *hdf; int keys_deleted = 0; int courses_processed = 0; int courses_in_use = 0; int sessions_deleted = 0; typedef struct login_node { char course[MAX_FILENAME + 1]; char realname[MAX_NAME + 1]; int minutes; struct login_node *next; } LOGIN_NODE; LOGIN_NODE *head = 0; static void add_to_list (char *course, char *realname, int minutes) { static LOGIN_NODE *ptr = 0; if (!head) { head = (LOGIN_NODE *) malloc (sizeof (LOGIN_NODE)); ptr = head; } else { ptr->next = (LOGIN_NODE *) malloc (sizeof (LOGIN_NODE)); ptr = ptr->next; } strncpy (ptr->course, course, MAX_FILENAME + 1); strncpy (ptr->realname, realname, MAX_NAME + 1); ptr->minutes = minutes; ptr->next = (LOGIN_NODE *) 0; } void free_login_list() { LOGIN_NODE *ptr; while(head) { ptr = head; head = head->next; free(ptr); } } static int login_record_cmp (LOGIN_NODE * a, LOGIN_NODE * b) { return (a->minutes > b->minutes ? 1 : a->minutes < b->minutes ? -1 : 0); } void sort_login_list () { LOGIN_NODE *q, *tail, *p, *r; if (head != NULL) { tail = head; while (tail->next) { q = tail->next; if (login_record_cmp (q, head) < 0) { tail->next = q->next; q->next = head; head = q; } else { r = head; p = r->next; while (login_record_cmp (q, p) > 0) { r = p; p = r->next; } if (q == p) tail = q; else { tail->next = q->next; q->next = p; r->next = q; } } } } } void set_data_list (const char *kind) { #define MAX_TMP_NAME 30 LOGIN_NODE *ptr; char name[MAX_TMP_NAME]; int i =0; sort_login_list (); for (ptr = head; ptr; ptr = ptr->next) { snprintf(name, MAX_TMP_NAME, "%s.%d.course", kind, i); cs_set_value(name, ptr->course); snprintf(name, MAX_TMP_NAME, "%s.%d.realname", kind, i); cs_set_value(name, ptr->realname); snprintf(name, MAX_TMP_NAME, "%s.%d.minutes", kind, i); cs_set_int_value(name, ptr->minutes); i++; } #undef MAX_TMP_NAME } void handle_key (char *fname, int *in_use, char *coursename, CONFIG_STRUCT *conf, time_t now) { FILE *fp; SESSION this_key; *in_use = 0; fp = fopen (fname, "r"); if (!fp) /* shouldn't happen, let's consider the key 'in use' */ { *in_use = 1; return; } if (fread (&this_key, sizeof (SESSION), 1, fp) != 1) /* shouldn't happen, consider key 'in use' */ { *in_use = 1; fclose (fp); return; } fclose(fp); if (this_key.expires > now) { if(this_key.group != ADMIN) /* don't report ADMIN keys */ { add_to_list (coursename, this_key.realname, (conf->key_expire - (this_key.expires - now)) / (time_t) 60); *in_use = 1; } } else { keys_deleted++; unlink (fname); } } void delete_stale_keys (int *in_use, char *coursename, CONFIG_STRUCT *conf, time_t now) { DIR *dir_p; struct dirent *dir_entry_p; char key_fname[MAX_PATH + 1]; char dirname[MAX_PATH + 1]; int key_used; *in_use = 0; snprintf (dirname, MAX_PATH + 1, "%skeys", conf->course_path); dir_p = opendir (dirname); if (!dir_p) { *in_use = 1; return; } while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { snprintf (key_fname, MAX_PATH + 1, "%s/%s", dirname, dir_entry_p->d_name); handle_key (key_fname, &key_used, coursename, conf, now); if (key_used) *in_use = 1; } } closedir (dir_p); } void visit_classroom ( char *coursename, time_t now) { int in_use; CONFIG_STRUCT conf; if (!read_configuration_file_ok(coursename, &conf)) /* shared_util.c */ return; if(conf.standalone) { delete_stale_keys (&in_use, coursename, &conf, now); if (in_use) courses_in_use++; courses_processed++; } } void do_standalone_courses(time_t now) { DIR *dir_p; /* used to traverse ../courses/ directory */ struct dirent *dir_entry_p; DIR *course_dir_p; /* used to traverse a directories within the ../courses directory */ struct dirent *course_dir_entry_p; char course_dir[MAX_PATH + 1]; char course_name[MAX_PATH + 1]; /* reset globals */ keys_deleted = 0; courses_processed = 0; courses_in_use = 0; free_login_list(); dir_p = opendir (COURSE_PATH); if (!dir_p) cs_critical_error(ERR_UNABLE_TO_OPEN_COURSES, ""); while (NULL != (dir_entry_p = readdir (dir_p))) /*for each directory within the ../courses directory */ { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { snprintf(course_dir, MAX_PATH + 1, "%s%s", COURSE_PATH, dir_entry_p->d_name); course_dir_p = opendir(course_dir); if(course_dir_p) { while (NULL != (course_dir_entry_p = readdir (course_dir_p))) /* for each course dir within ../courses/xx_subdir_xx.. */ { if (strcmp (course_dir_entry_p->d_name, ".") && strcmp (course_dir_entry_p->d_name, "..") && strcmp (course_dir_entry_p->d_name, GROUP_DESCRIPTION_FNAME) ) /* GROUP_DESCRIPTION_FNAME is #defined in shared_course_search.h */ { snprintf(course_name, MAX_PATH + 1, "%s/%s", dir_entry_p->d_name, course_dir_entry_p->d_name); visit_classroom (course_name, now); } } closedir(course_dir_p); } } } closedir(dir_p); set_data_list ("std"); cs_set_int_value("std_course_num", courses_processed); cs_set_int_value("std_course_inuse", courses_in_use); cs_set_int_value("std_delete_key", keys_deleted); } static int count_sessions(const char *username) { char user_dir[MAX_PATH + 1]; DIR *dir_p; struct dirent *dir_entry_p; char *ptr; int count = 0; /* sub_dir_name() is in shared_authenticate.c */ snprintf(user_dir,MAX_PATH + 1, "../%s/%c/%s", USERS_DIR, sub_dir_name(username), username); dir_p = opendir (user_dir); if (!dir_p) /* shouldn't happen, but lets not complain */ return 0; while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { ptr = strstr(dir_entry_p->d_name, KEY_FILE_EXTENSION); if(ptr && (strlen(ptr) == strlen(KEY_FILE_EXTENSION))) /* if file ends with KEY_FILE_EXTENSION */ count++; } } closedir(dir_p); return count; } static int delete_sessions(const char *username) { char user_dir[MAX_PATH + 1]; char session_fname[MAX_PATH + 1]; DIR *dir_p; struct dirent *dir_entry_p; char *ptr; int count = 0; /* sub_dir_name() is in shared_authenticate.c */ snprintf(user_dir,MAX_PATH + 1, "../%s/%c/%s", USERS_DIR, sub_dir_name(username), username); dir_p = opendir (user_dir); if (!dir_p) /* shouldn't happen, but lets not complain */ return 0; while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { ptr = strstr(dir_entry_p->d_name, KEY_FILE_EXTENSION); if(ptr && (strlen(ptr) == strlen(KEY_FILE_EXTENSION))) /* if file ends with KEY_FILE_EXTENSION */ { snprintf(session_fname, MAX_PATH + 1, "%s/%s", user_dir, dir_entry_p->d_name); unlink(session_fname); sessions_deleted++; } } } closedir(dir_p); return count; } void handle_central_key (const char *fname, time_t now) { FILE *fp; SESSION this_key; char count_string[50]; fp = fopen (fname, "r"); if(!fp) { return; } if (fread (&this_key, sizeof (SESSION), 1, fp) != 1) /* shouldn't happen, consider key 'in use' */ { fclose (fp); return; } fclose(fp); /* some keys might belong to an administrator entering a course's configuration via ** the super user menu. Handle these silently */ if (this_key.expires > now) { if(this_key.group != ADMIN) /* don't report ADMIN keys */ { snprintf(count_string, 50, "%d %s", count_sessions(this_key.username), hdf_get_value(hdf, "manwho_cgi", "course(s)")); add_to_list (count_string, this_key.realname, (MAX_KEY_EXPIRE - (this_key.expires - now)) / (time_t) 60); } courses_in_use++; } else { keys_deleted++; unlink (fname); if(this_key.group != ADMIN) delete_sessions(this_key.username); } } void do_central_courses(time_t now) { DIR *dir_p; char fname[MAX_PATH + 1]; struct dirent *dir_entry_p; char keydir[MAX_PATH + 1]; snprintf(keydir,MAX_PATH + 1, "../%s/%s", USERS_DIR, KEY_DIR); dir_p = opendir (keydir); if (!dir_p) cs_critical_error(ERR_UNABLE_TO_OPEN_KEYS, ""); /* reset globals */ keys_deleted = 0; courses_processed = 0; courses_in_use = 0; sessions_deleted = 0; free_login_list(); get_lang_string(&hdf); while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { snprintf (fname, MAX_PATH + 1, "%s/%s", keydir, dir_entry_p->d_name); handle_central_key (fname, now); courses_processed++; } } closedir(dir_p); set_data_list ("ctr"); cs_set_int_value("ctr_course_num", courses_processed); cs_set_int_value("ctr_course_inuse", courses_in_use); cs_set_int_value("ctr_delete_key", keys_deleted); cs_set_int_value("ctr_session_key", sessions_deleted); hdf_destroy(&hdf); } int main () { char key[MAX_KEY +1]; SESSION user; time_t now; cs_cgi_init(); read_param( key); validate_super_key(key, &user); /*shared_util.c */ set_admin_page(&user, key, 0, "super_manwho_cgi"); /* shared_super_menu.c */ cs_set_current_time(); /* shared_cs_util.c */ now = time(NULL); do_central_courses(now); do_standalone_courses(now); cs_cgi_display("super_manwho", 1); cs_cgi_destroy(); return 0; }