#include <linux/kmod.h> // 包含内核模块相关的头文件
#include <linux/kallsyms.h> // 包含内核符号表相关的头文件
#include <linux/types.h> // 包含内核类型定义的头文件
#include <linux/slab.h> // 包含内核内存分配相关的头文件
#include <linux/mm.h> // 包含内存管理相关的头文件
#include <linux/sched.h> // 包含调度相关的头文件
#include <linux/version.h> // 包含内核版本相关的头文件
#include <linux/ctype.h> // 包含字符类型相关的头文件

#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
# include <linux/sched/mm.h> // 包含调度和内存管理相关的头文件（仅在内核版本4.11.0及以上）
#endif

#include "util.h" // 包含自定义的util头文件

// 声明一个函数指针，用于访问进程虚拟内存
asmlinkage int (*_access_process_vm)(struct task_struct *, unsigned long, void *, int, int);

int util_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
	// 在内核版本4.11.0及以上，直接使用access_process_vm函数
	_access_process_vm = (void *) access_process_vm;
#else
	// 在内核版本4.11.0以下，通过符号表查找access_process_vm函数
	_access_process_vm = (void *) ksym_lookup_name("access_process_vm");
#endif
   
	// 如果函数指针为空，返回错误
	if (!_access_process_vm)
		return -EFAULT;

	return 0; // 初始化成功，返回0
}

/* 从mm/util.c文件中借用的函数 */

// 获取进程的命令行参数
int get_cmdline(struct task_struct *task, char *buffer, int buflen)
{
	int res = 0; // 初始化返回值
	unsigned int len; // 命令行参数的长度
	struct mm_struct *mm = get_task_mm(task); // 获取进程的内存描述符
	unsigned long arg_start, arg_end, env_start, env_end; // 命令行参数和环境变量的起始和结束地址

	if (!mm) // 如果内存描述符为空，跳转到out标签
		goto out;
	if (!mm->arg_end) // 如果命令行参数的结束地址为空，跳转到out_mm标签
		goto out_mm;

	down_read(&mm->mmap_sem); // 获取内存描述符的读锁
	arg_start = mm->arg_start; // 获取命令行参数的起始地址
	arg_end = mm->arg_end; // 获取命令行参数的结束地址
	env_start = mm->env_start; // 获取环境变量的起始地址
	env_end = mm->env_end; // 获取环境变量的结束地址
	up_read(&mm->mmap_sem); // 释放内存描述符的读锁

	len = arg_end - arg_start; // 计算命令行参数的长度

	if (len > buflen) // 如果长度大于缓冲区长度，截断长度
		len = buflen;

	// 读取进程的命令行参数到缓冲区
	res = _access_process_vm(task, arg_start, buffer, len, FOLL_FORCE);

	// 如果命令行参数的末尾被覆盖，假设应用程序使用了setproctitle(3)
	if (res > 0 && buffer[res-1] != '\0' && len < buflen) {
		len = strnlen(buffer, res); // 获取缓冲区的实际长度
		if (len < res) {
			res = len; // 更新返回值
		} else {
			len = env_end - env_start; // 计算环境变量的长度
			if (len > buflen - res) // 如果长度大于剩余缓冲区长度，截断长度
				len = buflen - res;
			// 读取进程的环境变量到缓冲区
			res += _access_process_vm(task, env_start, buffer+res, len, FOLL_FORCE);
			res = strnlen(buffer, res); // 获取缓冲区的实际长度
		}
	}
out_mm:
	mmput(mm); // 释放内存描述符
out:
	return res; // 返回读取的长度
}

/*
static int count_argc(const char *str)
{
	int count = 0; // 初始化参数计数
	bool was_space; // 标记上一个字符是否为空格

	for (was_space = true; *str; str++) {
		if (isspace(*str)) { // 如果当前字符为空格
			was_space = true; // 更新标记
		} else if (was_space) { // 如果当前字符不是空格且上一个字符为空格
			was_space = false; // 更新标记
			count++; // 增加参数计数
		}
	}

	return count; // 返回参数计数
}

int run_cmd(const char *cmd)
{
	char **argv; // 参数数组
	int ret; // 返回值
	int i; // 循环变量
	
	argv = argv_split(GFP_KERNEL, cmd, NULL); // 分割命令行参数
	if (argv) {
		ret = exec(argv); // 执行命令
		argv_free(argv); // 释放参数数组
	} else {
		ret = -ENOMEM; // 内存分配失败，返回错误
	}

	return ret; // 返回执行结果
}
*/