113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * utmpwatcher.c
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2006 Red Hat
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * see file 'COPYING' for use and warranty information
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This program is free software; you can redistribute it and/or
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * modify it under the terms of the GNU General Public License as
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * published by the Free Software Foundation; either version 2 of
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * the License, or (at your option) any later version.
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This program is distributed in the hope that it will be useful,
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * but WITHOUT ANY WARRANTY; without even the implied warranty of
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * GNU General Public License for more details.
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle.*
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * You should have received a copy of the GNU General Public License
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * along with this program; if not, write to the Free Software
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 02111-1307  USA
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Authors:
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *   Dan Walsh <dwalsh@redhat.com>
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle*/
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define _GNU_SOURCE
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/inotify.h>
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h>
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/stat.h>
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <syslog.h>
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <limits.h>
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <utmp.h>
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h>
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <pwd.h>
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "restorecond.h"
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "utmpwatcher.h"
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "stringslist.h"
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic struct stringsList *utmp_ptr = NULL;
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int utmp_wd = -1;
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleunsigned int utmpwatcher_handle(int inotify_fd, int wd)
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int changed = 0;
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct utmp u;
52188a028f747579fe74b817a997ae6209f3eb742fNicolas Iooss	const char *utmp_path = "/var/run/utmp";
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct stringsList *prev_utmp_ptr = utmp_ptr;
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (wd != utmp_wd)
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	utmp_ptr = NULL;
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	FILE *cfg = fopen(utmp_path, "r");
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!cfg)
60f5a700d1074a5e295127bbb6eb936f2ad4805fa7Joshua Brindle		exitApp("Error reading utmp file.");
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (fread(&u, sizeof(struct utmp), 1, cfg) > 0) {
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (u.ut_type == USER_PROCESS)
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			strings_list_add(&utmp_ptr, u.ut_user);
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fclose(cfg);
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (utmp_wd >= 0)
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		inotify_rm_watch(inotify_fd, utmp_wd);
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	utmp_wd =
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    inotify_add_watch(inotify_fd, utmp_path, IN_MOVED_FROM | IN_MODIFY);
72f5a700d1074a5e295127bbb6eb936f2ad4805fa7Joshua Brindle	if (utmp_wd == -1)
73f5a700d1074a5e295127bbb6eb936f2ad4805fa7Joshua Brindle		exitApp("Error watching utmp file.");
74f5a700d1074a5e295127bbb6eb936f2ad4805fa7Joshua Brindle
751236eef264f8022de4adc74750760a36dc420ab6Chris Adams	changed = strings_list_diff(prev_utmp_ptr, utmp_ptr);
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (prev_utmp_ptr) {
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		strings_list_free(prev_utmp_ptr);
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return changed;
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void watch_file(int inotify_fd, const char *file)
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct stringsList *ptr = utmp_ptr;
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (ptr) {
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		struct passwd *pwd = getpwnam(ptr->string);
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (pwd) {
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			char *path = NULL;
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (asprintf(&path, "%s%s", pwd->pw_dir, file) < 0)
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				exitApp("Error allocating memory.");
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			watch_list_add(inotify_fd, path);
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			free(path);
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ptr = ptr->next;
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid utmpwatcher_add(int inotify_fd, const char *path)
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (utmp_ptr == NULL) {
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		utmpwatcher_handle(inotify_fd, utmp_wd);
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	watch_file(inotify_fd, path);
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid utmpwatcher_free(void)
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (utmp_ptr)
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		strings_list_free(utmp_ptr);
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#ifdef TEST
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint main(int argc, char **argv)
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	read_utmp();
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#endif
120