#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <string.h>
#include <linux/version.h>

struct mylimits {
    int     limit_id;
    char    *limit;
};

void print_limits( int, char* );
int get_limits( char*, struct mylimits* );
void usage( char* , struct mylimits* );

int main( int argc, char **argv )
{
    struct mylimits my_rlimits[] = { { RLIMIT_AS, "RLIMIT_AS" },
                                     { RLIMIT_CORE, "RLIMIT_CORE" },
                                     { RLIMIT_CPU, "RLIMIT_CPU" },
                                     { RLIMIT_DATA, "RLIMIT_DATA" },
                                     { RLIMIT_FSIZE, "RLIMIT_FSIZE" },
                                     { RLIMIT_LOCKS, "RLIMIT_LOCKS" },
                                     { RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK" },
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
                                     { RLIMIT_MSGQUEUE, "RLIMIT_MSGQUEUE" },
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
                                     { RLIMIT_NICE, "RLIMIT_NICE"},
#endif
                                     { RLIMIT_NOFILE, "RLIMIT_NOFILE" },
                                     { RLIMIT_NPROC, "RLIMIT_NPROC" },  
                                     { RLIMIT_RSS, "RLIMIT_RSS" },
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
                                     { RLIMIT_RTPRIO, "RLIMIT_RTPRIO" },
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
                                     /*{ RLIMIT_RTTIME, "RLIMIT_RTTIME" },*/    
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
                                     { RLIMIT_SIGPENDING, "RLIMIT_SIGPENDING" },
#endif
                                     { RLIMIT_STACK, "RLIMIT_STACK" },
                                     { RLIMIT_OFILE, "RLIMIT_OFILE" },
                                     { -1, "EOF" } };
    int lim = -1;
    
    if( argc < 2 )
        usage( argv[0], my_rlimits );

    lim = get_limits( argv[argc-1], my_rlimits );
    if( lim == -1 )
        usage( argv[0], my_rlimits );

    print_limits( lim, argv[argc-1] );

    return( 0 );
}

void print_limits( int lim, char *limit )
{
    struct rlimit *rlimits;
    getrlimit( lim,  rlimits );
    printf( "RLIMIT: %s, RLIMIT_ID: %d, SOFT: %d, HARD: %d\n", limit, lim, (int) rlimits->rlim_cur, (int) rlimits->rlim_max );
}

int get_limits( char * limit, struct mylimits *l_limits )
{
    int count = 0;
    struct mylimits *local = l_limits;
    
    while( local[count].limit_id != -1 )
    {
        if( !strncmp( limit, local[count].limit, strlen( local[count].limit ) ) )
            return( local[count].limit_id );
        count++;
    }

    return( -1 );
}

void usage( char *app,  struct mylimits *l_limits )
{
    struct mylimits *local = l_limits;
    int count = 0;
    fprintf( stderr, "Usage: %s RLIMIT_NAME\n", app );
    fprintf( stderr, "RLIMIT_NAME could be one off:\n" );
    while( local[count].limit_id != -1 )
    {
        fprintf( stderr, " - %s\n",  local[count].limit );
        count++;
    }
    fprintf( stderr, "\nFor more informations about rlimits, please read man 2 getrlimit\n" );
    fprintf( stderr, "Thank you for choosing MeGaMaDdIn Products (c)\n" );
    exit( 1 );
}

