Tag: monitoring
ipchange.c
8. Juni 2015 16:15
                    /* ipchange.c
 *
 *  Netlink based IP monitor on specific interface.
 *  Executes command on new IPv4 address.
 *
 *  Sebastian Kricner
 *  tuxwave.net
 *  June 2014
 *
*/

#include <netlink/netlink.h>
#include <netlink/socket.h>
#include <netlink/msg.h>
#include <netlink/errno.h>
#include <netlink/route/link.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/types.h>
#include <string.h>

/*
gcc ipchange.c -o ipchange $(pkg-config --cflags --libs libnl-3.0 libnl-route-3.0)
*/

static char *interface;
static char *cmd;

static void parse_notification(struct nl_object *obj, void *arg)
{
    struct rtnl_addr *addr;
    char s_addr[128];

    int flags;
    char s_flags[128];

    unsigned int ifindex;
    char s_ifname[16];

    addr = (struct rtnl_addr *) obj;
    flags = rtnl_addr_get_flags(addr);
    ifindex = rtnl_addr_get_ifindex(addr);
    if(if_indextoname(ifindex, s_ifname))
    {
        nl_addr2str(rtnl_addr_get_local(addr), s_addr, sizeof(s_addr));
        rtnl_addr_flags2str(flags, s_flags, sizeof(s_flags));

        setenv("S_INTERFACE", s_ifname, 0);
        setenv("S_ADDRESS", s_addr, 0);
        setenv("S_FLAGS", s_flags, 0);

        if(strcmp(s_ifname, interface) == 0)
        {
            system(cmd);
            syslog(LOG_NOTICE, "command executed");
        }
    }
    return;
}

static int process_notification(struct nl_msg *msg, void *arg)
{
    struct nlmsghdr *msghdr = nlmsg_hdr(msg);
    if(msghdr->nlmsg_type == RTM_NEWADDR)
        nl_msg_parse(msg, &parse_notification, arg);
    return NL_OK;
}

static int start_monitor(char *interface, char *cmd)
{
    struct nl_sock *sk;
    int err;
    sk = nl_socket_alloc();
    if(!sk)
    {
        fprintf(stderr, "Could not allocate netlink socket.\n");
        exit(ENOMEM);
    }
    nl_socket_disable_seq_check(sk);
    nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, process_notification, NULL);
    if(err = nl_connect(sk, NETLINK_ROUTE))
    {
        fprintf(stderr, "netlink error: %s\n", nl_geterror(err));
        nl_socket_free(sk);
        sk = NULL;
        exit(err);
    }
    nl_socket_add_memberships(sk, RTNLGRP_IPV4_IFADDR, 0);
    while (1)
        nl_recvmsgs_default(sk);
    return 0;
}

static void daemonize(void)
{
    int pid;

    if(pid = fork())
    {
        exit(EXIT_SUCCESS);
    }
    else if(pid == 0)
    {
        close(0);
        close(1);
        close(2);
        setsid();
        syslog(LOG_NOTICE, "Daemonized");
        FILE *pidfile = fopen("/var/run/ipchange.pid", "w");
        fprintf(pidfile, "%d", getpid());
        fclose(pidfile);
    }
    else
    {
        perror("daemonize");
        exit(errno);
    }
    return;
}

int main(int argc, char **argv, char **envp)
{
    interface = "eth0";
    cmd = "foo";
    daemonize();
    start_monitor(interface, cmd);
    return(EXIT_SUCCESS);
}

                    
        
Download
Multi File Monitor
12. November 2012 04:30

Ein C Programm mit ncurses, welches mehrere Logfiles gleichzeitig anzeigt.
Mit Aktivitätsüberwachung.

                    /*
 * 	Multi File Monitor
 * 	Sebastian Kricner
 * 	tuxwave.net 
 * 	February 2011
 *
 * 	Description:
 * 	This is a monitor for usual textfiles like logfiles.
 * 	It monitors multiple files using ncurses and inotify.
 * 	Use down+up arrows for selecting files and q for quitting.
 *
 * 	Compiling:
 * 	gcc multifilemon.c -o multifilemon -lncurses -lpthread
 *
 * 	Why this?
 * 	It was for coding practice.
 * 	This program can still be optimized and extended :)
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fcntl.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <curses.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>

#include <sys/inotify.h>
#include <sys/ioctl.h>

static void usage(char *name);
static void init_windows(void);
static void interaction(void);

static void *filewatch(void* arg);
static void *logfilewatch(void *arg);

void sigint_handler(int sig);
void sigwinch_handler(int sig);

char **arguments;
int *argcount, curfile,  threads_created;
WINDOW *filewindow, *sub_filewindow, *logwindow, *sub_logwindow, *infowindow, *sub_infowindow;
pthread_t logfilewatch_thread, filewatch_thread; 

sem_t locker;

int main(int argc, char **argv, char **envp)
{
	int count;
	struct stat statbuf;

	argcount = &argc;	
	arguments = argv;

	curfile = 1;
	threads_created = 0;

	if(argc == 1)
	{
		usage(argv[0]);
	}
	for(count = 1; count < argc; count++)
	{
		if(stat(argv[count], &statbuf) == 0)
		{
			if(!S_ISREG(statbuf.st_mode))
			{
				fprintf(stderr, "Error: No valid file: %s\n", argv[count]);
				usage(argv[0]);
			}
		}
		else
		{
			fprintf(stderr, "Error: No valid file: %s\n", argv[count]);
			usage(argv[0]);
		}
	}
	initscr();
	if(!has_colors() || !isatty(fileno(stdout)))
	{   
		endwin();
		fprintf(stderr, "Error - no color support available\n");
		exit(EXIT_FAILURE);
	} 
	if(start_color() != OK) 
	{   
		endwin();    
		fprintf(stderr, "Could not initialize colors\n");
		exit(EXIT_FAILURE);
	} 
	clear();
	cbreak();
	noecho();
	nonl();
	keypad(stdscr, 1);
	curs_set(0);
	use_default_colors();
	init_pair(1, COLOR_RED, -1);
	init_windows();
	exit(EXIT_SUCCESS);
}

void sigwinch_handler(int sig)
{
	endwin();
	fprintf(stderr, "This application does not support sigwinch-resizing, sorry\n");
	exit(EXIT_SUCCESS);
	return;
}

void sigint_handler(int sig)
{
	pthread_cancel(filewatch_thread);
 	pthread_cancel(logfilewatch_thread);
	endwin();
	exit(EXIT_SUCCESS);
	return;
}

static void usage(char *name)
{
	printf("Usage:\n"
	"%s [files...]\n", name);
	exit(EXIT_FAILURE);
}

static void init_windows(void)
{
	int count, max_y, max_x;
	getmaxyx(stdscr, max_y, max_x);

	filewindow = newwin(max_y-3, max_x/3, 0, 0);
	sub_filewindow = subwin(filewindow, max_y-5, (max_x/3)-2, 1, 1);
	scrollok(sub_filewindow, 1);

	logwindow = newwin(max_y-3, (max_x-(max_x/3)-1), 0, (max_x/3)+1);
	sub_logwindow = subwin(logwindow, max_y-5, max_x-(max_x/3)-3, 1, (max_x/3)+2);
	scrollok(sub_logwindow, 1);

	infowindow = newwin(3, max_x, max_y-3, 0);
	sub_infowindow = subwin(infowindow, 1, max_x-2, max_y-2, 1);

	box(filewindow, 0, 0);
	box(logwindow, 0, 0);
	box(infowindow, 0, 0);

	for(count = 1;count < *argcount;count++)
	{
		wprintw(sub_filewindow, "%s\n", *(arguments+count));
	}

	wprintw(sub_infowindow, "%s", *(arguments+1));

	refresh();
	wrefresh(filewindow);
	wrefresh(logwindow);
	wrefresh(infowindow);
	if(threads_created == 0)
	{
		interaction();
	}
	return;
}

static void interaction(void)
{
	int key;
	sem_init(&locker, 0, 0);

	pthread_create(&filewatch_thread,NULL,filewatch,NULL); 
	pthread_create(&logfilewatch_thread,NULL,logfilewatch,*(arguments+1)); 
	threads_created = 1;
	
	struct sigaction act[2];
	sigfillset(&act[0].sa_mask);
	sigdelset(&act[0].sa_mask, SIGWINCH);
	act[0].sa_handler = sigwinch_handler;
	sigaction(SIGWINCH, &act[0], 0);

	sigfillset(&act[1].sa_mask);
	sigdelset(&act[1].sa_mask, SIGINT);
	act[1].sa_handler = sigint_handler;
	sigaction(SIGINT, &act[1], 0);

	while(1)
	{
		key = getch();
		switch(key)
		{
			case KEY_UP:
					if(curfile > 1)
					{
						if(pthread_cancel(logfilewatch_thread))
						{
							endwin();
							fprintf(stderr, "pthread error\n");
							exit(EXIT_FAILURE);
						}
						curfile--;
						pthread_create(&logfilewatch_thread,NULL,logfilewatch,*(arguments+curfile)); 
					}
			break;
			case KEY_DOWN:
					if(curfile < *argcount-1)
					{
						if(pthread_cancel(logfilewatch_thread))
						{
							endwin();
							fprintf(stderr, "pthread error\n");
							exit(EXIT_FAILURE);
						}
						curfile++;
						pthread_create(&logfilewatch_thread,NULL,logfilewatch,*(arguments+curfile)); 
					}
			break;
			case 'q':
					pthread_cancel(filewatch_thread);
					pthread_cancel(logfilewatch_thread);
					endwin();
					exit(EXIT_SUCCESS);
			break;
		}
	}
	return;
}

static void *filewatch(void* arg)
{
	int inotify_fd, count, icount, len, cur_y, cur_x;
	char inobuf[1024 * (sizeof(struct inotify_event)+16)];

	int res;
	res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	if(res != 0)
	{
		wclear(sub_filewindow);
		wprintw(sub_filewindow, "pthread error");
		touchwin(filewindow);
		wrefresh(filewindow);
		pthread_exit(0);
	}
	res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
	if(res != 0)
        {   
		wclear(sub_filewindow);
		wprintw(sub_filewindow, "pthread error");
		touchwin(filewindow);
		wrefresh(filewindow);
                pthread_exit(0);
        }

	if((inotify_fd = inotify_init()) < 0)
	{
		wclear(sub_filewindow);
		wprintw(sub_filewindow, "inotify error");
		touchwin(filewindow);
		wrefresh(filewindow);
		pthread_exit(0);
	}
	for(count = 1;count < *argcount; count++)
	{
		if((inotify_add_watch(inotify_fd, *(arguments+count), IN_MODIFY)) == -1)
		{
			wclear(sub_filewindow);
			wprintw(sub_filewindow, "inotify error");
			touchwin(filewindow);
			wrefresh(filewindow);
			close(inotify_fd);
			pthread_exit(0);
		}
	}
	while((len = read(inotify_fd, inobuf, sizeof(struct inotify_event))))
	{
		while(icount < len)
		{
			struct inotify_event *event = (struct inotify_event *) &inobuf[icount];
			wclear(sub_filewindow);
			for(count = 1;count < *argcount;count++)
			{
				if(event->wd == count)
				{
					wattrset(sub_filewindow, COLOR_PAIR(1));
					wprintw(sub_filewindow, "%s\n", *(arguments+count));
					wattroff(sub_filewindow, COLOR_PAIR(1));
					if(curfile == count)
					{
						sem_post(&locker);
					}
				}
				else
				{
					wprintw(sub_filewindow, "%s\n", *(arguments+count));
				}
			}
			icount += sizeof(struct inotify_event) + event->len;
		}
		touchwin(filewindow);
		wrefresh(filewindow);
		icount=0;
	}
	pthread_exit(0);
}

static void *logfilewatch(void *arg)
{
	char *file = (char *) arg;
	int logfile, state, character;
	int res;
	res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	if(res != 0)
	{
		wclear(sub_logwindow);
		wprintw(sub_logwindow, "pthread error");
		touchwin(logwindow);
		wrefresh(logwindow);
		pthread_exit(0);
	}
	res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
	if(res != 0)
        {   
		wclear(sub_logwindow);
		wprintw(sub_logwindow, "pthread error");
		touchwin(logwindow);
		wrefresh(logwindow);
                pthread_exit(0);
        }
	wclear(sub_logwindow);
	touchwin(logwindow);
	wrefresh(logwindow);
	wclear(sub_infowindow);
	wprintw(sub_infowindow, "%s", file);
	touchwin(infowindow);
	wrefresh(infowindow);
	logfile = open(file, O_RDONLY);
	if(logfile == -1)
	{
		wprintw(sub_logwindow, "Could not open %s", file);
		touchwin(logwindow);
		wrefresh(logwindow);
		pthread_exit(0);
	}
	lseek(logfile, -1024, SEEK_END);
	while((state = read(logfile, &character, 1)) != -1)
	{
		if(state == 0)
		{
			sem_wait(&locker);
			continue;
		}
		if((char) character == '\n')
		{
			wprintw(sub_logwindow, "%c", character);
			touchwin(logwindow);
			wrefresh(logwindow);
		}
		else
		{
			wprintw(sub_logwindow, "%c", character);
			touchwin(logwindow);
		}
	}
	close(logfile);
	pthread_exit(0);
}

                    
        
Download