• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = "/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