#include <sys/types.h>
#ifndef _LP64
#error "not using 64bit mode"
#endif

#include <sys/resource.h>
#if ! defined(RLIMIT_NOFILE) && defined(RLIMIT_OFILE)
#define RLIMIT_NOFILE RLIMIT_OFILE
#endif

#include <unistd.h>
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#define MAX 65536

int
main( int argc, char* argv[] )
{
  struct rlimit limit;
  FILE** fd;
  char   fn[256];
  long   i, maxfd = ( argc != 2 ) ? MAX : strtol(argv[1],0,0);

  /* obtain hard/soft limit */
  if ( getrlimit( RLIMIT_NOFILE, &limit ) == -1 ) {
    perror( "unable to obtain limits" );
    return 1;
  } else {
    printf( "FD limit = { hard : %d, soft : %d }\n",
	    limit.rlim_max, limit.rlim_cur );
  }

  /* check back with soft/hard limit of system */
  if ( maxfd > limit.rlim_cur ) {
    /* check with hardlimit, complain if exceeded */
    if ( maxfd > limit.rlim_max ) {
      fputs( "hardlimit exceeded!\n", stderr );
      return 1;
    } else {
      limit.rlim_cur = maxfd;
      if ( setrlimit( RLIMIT_NOFILE, &limit ) == -1 ) {
	perror( "unable to set new soft limit" );
	return 1;
      }
    }
  }
  
  assert( (fd = malloc( sizeof(FILE*) * maxfd )) != NULL );
  for (i=STDERR_FILENO+1; i<maxfd; ++i)
    {
      sprintf( fn, "/tmp/%05d.xx", i );
      if ( (fd[i] = fopen( fn, "w" )) == NULL ) 
	{
	  printf( "%d files opened\n", i );
	  perror( "fopen" );
	  return 1;
	}
    }
      
  for (i=STDERR_FILENO+1; i<maxfd; ++i)
    {
      if ( fprintf( fd[i], "testing\n" ) <= 0 )
	{
	  printf( "%d files opened\n", i );
	  perror( "fprintf" );
	  return 1;
	}
    }

  for (i=STDERR_FILENO+1; i<maxfd; ++i)
    {
      if ( fclose( fd[i] ) == EOF )
	{
	  printf( "%d files opened\n", i );
	  perror( "fclose" );
	  return 1;
	}
      sprintf( fn, "/tmp/%05d.xx", i );
      if ( remove(fn) == -1 ) 
	{
	  printf( "%d files opened\n", i );
	  perror( "remove" );
	  return 1;
	}
    }

  printf( "success for %d FDs\n", maxfd );
  free( (void*) fd );
  return 0;
}

