/*
 * Copyright (C) 1999-2000 Wojciech Purczynski <wp@elzabsoft.pl>
 *
 * THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY
 * IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY
 * THE FREE SOFTWARE  FOUNDATION;  EITHER  VERSION 2 OF THE LICENSE, OR
 * (AT YOUR OPTION) ANY LATER VERSION.
 *
 * THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
 * BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED  WARRANTY OF
 * MERCHANTABILITY OR FITNESS  FOR A PARTICULAR  PURPOSE.  SEE THE
 * GNU GENERAL PUBLIC LICENSE FOR MORE DETAILS.
 */

#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>

#if CONFIG_MODVERSIONS
#include <linux/modversions.h>
#endif

#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/dcache.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/malloc.h>

#include "global.h"
#include "config.h"
#include "lib.h"

void log(rule_t * r, int lvl, const char *exe, const char *msg, const char *arg)
{
	if (r->log_level==LOG_NOTHING) return;
	if (lvl<r->log_level) return;
	
	if (lvl==LOG_SECURITY)
		printk(KERN_WARNING "%.1024s: SECURITY %.1024s"
		" (%u:%u:%u:%u) %.1024s %.1024s\n", NAME, exe,
		PID, PPID, UID, EUID, msg, arg?arg:"");
	else
		printk(KERN_INFO "%.1024s: %.1024s"
		" (%u:%u:%u:%u) %.1024s %.1024s\n", NAME, exe,
		PID, PPID, UID, EUID, msg, arg?arg:"");
}

/* modified version od d_path() */
char *resolve_path(struct dentry *dentry, char *buffer, int buflen)
{
	char * end = buffer+buflen;
	char * retval;

	*--end = '\0';
	buflen--;
	if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
		buflen -= 10;
		end -= 10;
		memcpy(end, " (deleted)", 10);
	}

	/* Get '/' to the right */
	retval = end-1;
	*retval = '/';

	for (;;) {
		struct dentry * parent;
		int namelen;

		dentry = dentry->d_covers;
		parent = dentry->d_parent;
		if (dentry == parent)
			break;
		namelen = dentry->d_name.len;
		buflen -= namelen + 1;
		if (buflen < 0)
			break;
		end -= namelen;
		memcpy(end, dentry->d_name.name, namelen);
		*--end = '/';
		retval = end;
		dentry = parent;
	}
	return retval;
}

/*
 * Most of this code was ripped from kernel source.
 * Name got with get_exename must be released with put_exename()
 */
char *get_exename(void)
{
	struct vm_area_struct *vma;
	struct dentry *entry=NULL;
	char *result, *tmp;
	char exenamebuf[PATH_MAX];

	if (!current->mm) {
		printk(KERN_ERR NAME ": Unable to resolve filename");
		return NULL;
	}
	
	vma=current->mm->mmap;
	while (vma) {
		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
			entry=vma->vm_file->f_dentry;
			break;
		}
		vma=vma->vm_next;
	}
	
	if (entry) result=resolve_path(entry, exenamebuf, sizeof(exenamebuf));
	else result=NULL;
	
	if (!result) {
		printk(KERN_ERR NAME ": Unable to resolve filename");
		return NULL;
	}
	
	tmp=kmalloc(strlen(result)+1, GFP_KERNEL);
	if (!tmp) {
		printk(KERN_ERR NAME ": Unable to resolve filename");
		return NULL;
	}

	return strcpy(tmp, result);
}
