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
utmpwatcher_handle(int inotify_fd,int wd)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
watch_file(int inotify_fd,const char * file)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
utmpwatcher_add(int inotify_fd,const char * path)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
utmpwatcher_free(void)107 void utmpwatcher_free(void)
108 {
109 if (utmp_ptr)
110 strings_list_free(utmp_ptr);
111 }
112
113 #ifdef TEST
main(int argc,char ** argv)114 int main(int argc, char **argv)
115 {
116 read_utmp();
117 return 0;
118 }
119 #endif
120