/*
#Autor: Rodrigo Ferreira Baroni
#Data: 02/02/2007 
#Licença: GPL 2.0

  procinfo.c: arquivo fonte para construção de um módulo do kernel (procinfo.ko)
  que na sua inserção imprime algumas informações dos processos sendo
  executados, através do percurso pelas task_struct internas contidas no kernel.

*/

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>

#include <linux/sched.h>

static void fill_column( int len, int column_size )
{
	int 	i;
	for( i = len; i < column_size; i++ )
		printk( " " );
}

static char * int_to_str( int integer, int bufsize )
{
	int	i;
	int	base;
	int	digit;
	int	first;
	char * 	str_number;

	/* one size more to the terminal string simbol '\0' */ 
	str_number = ( char * ) kmalloc( ( bufsize + 1 ) * sizeof( char ), GFP_KERNEL );

	if( ! str_number )
	{
		printk( KERN_ALERT "System with no memory available. Aborting\n" );
		return NULL;
	}

	/* Generating the number by getting each decimal number using 
	 * digit =  integer / decimal base 
	 * E.g: integer 123, desired string buffer:
	 * buf = [ 1 | 2 | 3 ] = [ 123/100 | 23/10 | 3/1 ] */

	base = 1;
	for( i = 0; ( i <= bufsize - 1 ); i++  )
		base *= 10;

	first = 0;
	for( i = 0; i <= bufsize; i++ )
	{	
		digit = integer / base;
		integer = integer % base;
		if( digit == 0 && first == i )
		{
			str_number[ i ] = 32; /* 32 is the num of the space in the ascii table */
			first++;
		}
		else
			str_number[ i ] = digit + 48; /* the ascii code of the number */
		base /= 10;
	}
	str_number[ bufsize ] = '\0';
	return str_number;
}

static int procinfo_init( void )
{
	struct task_struct * 	task;
	char *			str;

	printk( KERN_ALERT "   PID   USER PR COMMAND\n" );

	for_each_process( task ) 
	{
		str = int_to_str( task->pid, 6 );
		printk( "%s ", str );
		kfree( str );

		printk( "%i ", task->uid );

		printk( "%i ", task->prio );

		printk( "%s", task->comm );
		fill_column( strlen( task->comm ), 20 );

		printk( "\n" );
	}

	return 0;
}

static void procinfo_exit( void )
{
	printk( KERN_ALERT "out, out, brief candle!\n" );
}

module_init( procinfo_init );
module_exit( procinfo_exit );

MODULE_LICENSE( "GPL" );
MODULE_AUTHOR( "Baroni" );

