Home | History | Annotate | Download | only in restorecond
      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 (at) 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 
     48 unsigned int utmpwatcher_handle(int inotify_fd, int wd)
     49 {
     50 	int changed = 0;
     51 	struct utmp u;
     52 	const 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 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 
     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 
     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 
    107 void utmpwatcher_free(void)
    108 {
    109 	if (utmp_ptr)
    110 		strings_list_free(utmp_ptr);
    111 }
    112 
    113 #ifdef TEST
    114 int main(int argc, char **argv)
    115 {
    116 	read_utmp();
    117 	return 0;
    118 }
    119 #endif
    120