1 /* 2 * utmpwatcher.c 3 * 4 * Copyright (C) 2006 Red Hat 5 * see file 'COPYING' for use and warranty information 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 .* 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 20 * 02111-1307 USA 21 * 22 * Authors: 23 * Dan Walsh <dwalsh@redhat.com> 24 * 25 * 26 */ 27 28 #define _GNU_SOURCE 29 #include <sys/inotify.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <syslog.h> 36 37 #include <limits.h> 38 #include <utmp.h> 39 #include <sys/types.h> 40 #include <pwd.h> 41 #include "restorecond.h" 42 #include "utmpwatcher.h" 43 #include "stringslist.h" 44 45 static struct stringsList *utmp_ptr = NULL; 46 static int utmp_wd = -1; 47 48 unsigned int utmpwatcher_handle(int inotify_fd, int wd) 49 { 50 int changed = 0; 51 struct utmp u; 52 const char *utmp_path = "/var/run/utmp"; 53 struct stringsList *prev_utmp_ptr = utmp_ptr; 54 if (wd != utmp_wd) 55 return -1; 56 57 utmp_ptr = NULL; 58 FILE *cfg = fopen(utmp_path, "r"); 59 if (!cfg) 60 exitApp("Error reading utmp file."); 61 62 while (fread(&u, sizeof(struct utmp), 1, cfg) > 0) { 63 if (u.ut_type == USER_PROCESS) 64 strings_list_add(&utmp_ptr, u.ut_user); 65 } 66 fclose(cfg); 67 if (utmp_wd >= 0) 68 inotify_rm_watch(inotify_fd, utmp_wd); 69 70 utmp_wd = 71 inotify_add_watch(inotify_fd, utmp_path, IN_MOVED_FROM | IN_MODIFY); 72 if (utmp_wd == -1) 73 exitApp("Error watching utmp file."); 74 75 changed = strings_list_diff(prev_utmp_ptr, utmp_ptr); 76 if (prev_utmp_ptr) { 77 strings_list_free(prev_utmp_ptr); 78 } 79 return changed; 80 } 81 82 static void watch_file(int inotify_fd, const char *file) 83 { 84 struct stringsList *ptr = utmp_ptr; 85 86 while (ptr) { 87 struct passwd *pwd = getpwnam(ptr->string); 88 if (pwd) { 89 char *path = NULL; 90 if (asprintf(&path, "%s%s", pwd->pw_dir, file) < 0) 91 exitApp("Error allocating memory."); 92 watch_list_add(inotify_fd, path); 93 free(path); 94 } 95 ptr = ptr->next; 96 } 97 } 98 99 void utmpwatcher_add(int inotify_fd, const char *path) 100 { 101 if (utmp_ptr == NULL) { 102 utmpwatcher_handle(inotify_fd, utmp_wd); 103 } 104 watch_file(inotify_fd, path); 105 } 106 107 void utmpwatcher_free(void) 108 { 109 if (utmp_ptr) 110 strings_list_free(utmp_ptr); 111 } 112 113 #ifdef TEST 114 int main(int argc, char **argv) 115 { 116 read_utmp(); 117 return 0; 118 } 119 #endif 120