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