blob: 62ad2e98aff3273deb307e85ddf1058cc2ef548f [file] [log] [blame]
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001/*
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
45static struct stringsList *utmp_ptr = NULL;
46static int utmp_wd = -1;
47
48unsigned int utmpwatcher_handle(int inotify_fd, int wd)
49{
50 int changed = 0;
51 struct utmp u;
Nicolas Iooss188a0282014-09-14 23:41:48 +020052 const char *utmp_path = "/var/run/utmp";
Joshua Brindle13cd4c82008-08-19 15:30:36 -040053 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)
Joshua Brindlef5a700d2009-02-16 11:48:37 -050060 exitApp("Error reading utmp file.");
Joshua Brindle13cd4c82008-08-19 15:30:36 -040061
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);
Joshua Brindlef5a700d2009-02-16 11:48:37 -050072 if (utmp_wd == -1)
73 exitApp("Error watching utmp file.");
74
Chris Adams1236eef2010-08-12 14:51:28 -050075 changed = strings_list_diff(prev_utmp_ptr, utmp_ptr);
Joshua Brindle13cd4c82008-08-19 15:30:36 -040076 if (prev_utmp_ptr) {
Joshua Brindle13cd4c82008-08-19 15:30:36 -040077 strings_list_free(prev_utmp_ptr);
78 }
79 return changed;
80}
81
82static 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
99void 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
107void utmpwatcher_free(void)
108{
109 if (utmp_ptr)
110 strings_list_free(utmp_ptr);
111}
112
113#ifdef TEST
114int main(int argc, char **argv)
115{
116 read_utmp();
117 return 0;
118}
119#endif