#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>

#define perror(string) fprintf(stderr,"%s:%d %s\n", string, errno, strerror(errno))

char **file_ptr;
int more_sockets;
pthread_mutex_t mutex;
pthread_cond_t cond;
void *new_connection(void*arg);
void  end_connection(void*arg);
void netfinger(const char *name, const char *host, int lflag);
char *nexthost(void);
FILE *nexthostfile(void);

int main(int argc,char *argv[])
{
  char  *hostname;

  pthread_attr_t attr;
  pthread_t thread_id;

  pthread_init();
  pthread_mutex_init(&mutex,NULL);
  pthread_cond_init(&cond,NULL);
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  more_sockets=atoi(argv[1]);
  file_ptr=argv+2;

  while((hostname=nexthost()))
    {
      pthread_mutex_lock(&mutex);
      while(more_sockets<=0)
	pthread_cond_wait(&cond,&mutex);
      more_sockets--;
      pthread_mutex_unlock(&mutex);
      
      pthread_create(&thread_id, &attr, new_connection, hostname);
    }
  pthread_exit(0);
  return(0);
}

void *new_connection(void *arg)
{
  char *hostname=arg;

  pthread_cleanup_push(end_connection, hostname);
  netfinger("",hostname,0);
  return (void*)0;
}

void end_connection(void *arg)
{
  free(arg);
  pthread_mutex_lock(&mutex);
  more_sockets++;
  pthread_mutex_unlock(&mutex);
  pthread_cond_signal(&cond);
}



/* returns malloc'd space!! beware */
#define BIGBUFSIZE 1000
char *nexthost(void)
{
  static char buf[BIGBUFSIZE]; 
  char *temp=NULL;
  static FILE* hostfile=NULL;
  static int line=0;
  int a=0;

  while (!temp || !*temp) {
    while (!hostfile || feof(hostfile) || ferror(hostfile))
      {
	if (hostfile && ferror(hostfile)) 
	  perror(*file_ptr);
	if (hostfile)
	  fclose(hostfile);
	hostfile=nexthostfile();
	line=0;
	if (hostfile == NULL)
	  return NULL;
      }

    /* conscious decision, if buffer overfills (say "foobarbaz")
       go ahead and return truncated host (ie "fooba") then leave
       rest for next time (ie "rbaz") user might guess what's going on */ 
    /* I don't like the idea of a fixed buffer anyways and may fix this */ 
  
    line++;
    fgets(buf, BIGBUFSIZE, hostfile);
    if ((temp=memchr(buf,'\n',BIGBUFSIZE)) ||
	(temp=memchr(buf,'\0',BIGBUFSIZE))   )
      {
	*temp='\0';
	temp=malloc(a=temp-buf+1),
	memcpy(temp,buf,a);
      }
    else
      {
	buf[BIGBUFSIZE-1]='\0';
	fprintf(stderr,"%s: Host name too long, buffer overflow, sorry\n", buf);
	temp=malloc(BIGBUFSIZE);
	memcpy(temp,buf,BIGBUFSIZE);
      }
  }
  return temp;
}

FILE *nexthostfile(void)
{
  /* for now just step file_ptr though argv and assume they're all files,
     We could preprocess args and generate a list of filenames */
  FILE* temp=NULL;
  while(!temp)
    {
      if (!*file_ptr)
	return NULL;
      temp=fopen(*file_ptr,"r");
      if (!temp)
	temp=NULL;
      file_ptr++;
    }
  return temp;
}
