blob: f818bbf533f1a5ec2af9b1cf01743665670aee00 [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;
52 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 config 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 (prev_utmp_ptr) {
73 changed = strings_list_diff(prev_utmp_ptr, utmp_ptr);
74 strings_list_free(prev_utmp_ptr);
75 }
76 return changed;
77}
78
79static void watch_file(int inotify_fd, const char *file)
80{
81 struct stringsList *ptr = utmp_ptr;
82
83 while (ptr) {
84 struct passwd *pwd = getpwnam(ptr->string);
85 if (pwd) {
86 char *path = NULL;
87 if (asprintf(&path, "%s%s", pwd->pw_dir, file) < 0)
88 exitApp("Error allocating memory.");
89 watch_list_add(inotify_fd, path);
90 free(path);
91 }
92 ptr = ptr->next;
93 }
94}
95
96void utmpwatcher_add(int inotify_fd, const char *path)
97{
98 if (utmp_ptr == NULL) {
99 utmpwatcher_handle(inotify_fd, utmp_wd);
100 }
101 watch_file(inotify_fd, path);
102}
103
104void utmpwatcher_free(void)
105{
106 if (utmp_ptr)
107 strings_list_free(utmp_ptr);
108}
109
110#ifdef TEST
111int main(int argc, char **argv)
112{
113 read_utmp();
114 return 0;
115}
116#endif