/*
*
*                             4tune
*
*
*                                            Luca Favaro
*
*/

#include <string.h>
#include <dos.h>
#include <stdio.h>
#include <io.h>
#define version "4Tune - Version 2.60 - June 1990 - by Luke"

  int p_opt, f_opt, o_opt = 0;
  char name[30];
  FILE *stream;
  unsigned long flength;
  unsigned long offset;
  char uno[] = "$e[s$e[H$e[0;1;37;44m";
  char due[] = "$e[K$e[u$e[0m";
  char full[256];
  char text[81];
  unsigned int psp;
  int size;
  int full_size;
  char far *env;

/* --------------------------------------------------------------------*/
/*	 main							       */
/* --------------------------------------------------------------------*/

main(int argc, char *argv[])
{
  int num = 0;

/*  Set p_opt, f_opt and o_opt accordingly to the options present (1=present) */

  while ((++num) < argc)
  {
	if (stricmp (argv[num],"?") == 0)
	{
		disp_usage();
		continue;
	}
	if (stricmp (argv[num],"/p") == 0)
	{
		p_opt = 1;
		continue;
	}
	if (stricmp (argv[num],"/o") == 0)
	{
		o_opt = 1;
		continue;
	}
	f_opt = num;
  }

  if (f_opt != 0)		       /* is the FILE opt. present?... */
	 strcpy(name,argv[f_opt]);     /* ...YES! Let's use the optional name  */
  else
	 strcpy(name,"TUNE");          /* ...NO! Let's use "TUNE" filename */
  open_file();
  while (strlen(text) == 0)
  {
	find_random();
	get_string();
  }
  if (o_opt != 0)     printf("\nString lenght:   %d\n\n",strlen(text));
  if (p_opt != 0)
  {
	printf("\n%s",version); /* if P option present display an header .... */
	find_psp();		/* ...then look for PSP... */
	extract_prompt();	/* ...extract the PROMPT variable... */

		 /* if we run out of environment space, display a message .... */

	if  ((43 + 80) >= size)
		reset_pr();			/* ...reset prompt and exit */

	write_in_psp();				/* ...and write in it */
  }
  else			/* if no P option present, just display the fortune */
	disp_string();
  fcloseall();			/* ....done */
  exit(1);
}

/* --------------------------------------------------------------------*/
/*  this function opens the file				       */
/* --------------------------------------------------------------------*/
open_file()
{
  stream = fopen(name,"r");                          /* open the file */
  if (stream == NULL)				     /* if no FILE found...    */
  {
	 printf ("\nCan't open input file: %s\n",name);
	 exit(1);
  }
  flength = filelength (fileno(stream)) - 2; /* get length of FILE in bytes */
}

/* --------------------------------------------------------------------*/
/*  this function gives a random value between 1 and the file size     */
/* --------------------------------------------------------------------*/
find_random()
{
  unsigned long rand_value1, rand_value2;
  long now;
  int loop;

/* Generate random seed */

  time(&now);
  loop = abs(* (char *) 0x0440);
  srand(loop + now);

/* Get first random number */

  loop = abs(* (char *) 0x046C);
  while (loop >= 0)
  {
	 loop--;
	 rand();
  }
  rand_value1 = ((long) rand() * 10000) / 32767;   /* number between 0 and 9999 */

  rand_value1 = rand_value1 * 100;

/* Get second random number */

  loop = abs(* (char *) 0x046D);
  while (loop >= 0)
  {
	 loop--;
	 rand();
  }

/* rand_value can be a number between 0 and 1,000,000 */

  rand_value2 = rand_value1 + (((long) rand() * 100) / 32767);

/* define an offset in the file */

  offset =  ((float) rand_value2 / 1000000.0) * flength;

  if (o_opt == 1)
  {
	printf ("\nRandom value1:   %lu",rand_value1 / 100);
	printf ("\nRandom value2:   %lu",rand_value2 - rand_value1);
  	printf ("\nFile lenght:     %lu",flength);
	printf ("\nOffset:          %lu",offset);
  }
}

/* --------------------------------------------------------------------*/
/*	  This function reads a string from the file.                  */
/* --------------------------------------------------------------------*/
get_string()
{
  char *pointer_f;
  int pointer_t = 0;

  fseek(stream, offset, 0);	    	/* read 162 character starting from the... */
  fread(full, 162, 1, stream);		/* ...specifed offset in the file */
  pointer_f = strchr(full,'\n');        /* Find first <CR> in string. */
  pointer_f++;                          /* move to the next character.... */
  if ((strchr(pointer_f,'\n') - pointer_f) > 80)
  {
	printf ("\nFile contains a string longer than 80 characters/n");
	exit (1);
  }
  while (*pointer_f != '\n')            /* ...copy from full[] to text[].. */
  {                                     /* ...'till next <CR>  */
	text[pointer_t] = *pointer_f;
	pointer_f++;
	pointer_t++;
  }
  text[pointer_t--] = '\0';
}

/* --------------------------------------------------------------------*/
/*	This function finds command.com PSP and environment size       */
/* --------------------------------------------------------------------*/
find_psp()
{
  unsigned *tmp;

  psp = _psp;
  tmp = MK_FP(psp,22);

  while (psp != *tmp)
  {
	 psp = *tmp;
  }
  env = MK_FP(*(unsigned far *)MK_FP(psp,44),0);
  size = 16 * *(int far *) MK_FP(FP_SEG(env)-1,3);
  full_size = size;
}

/* --------------------------------------------------------------------*/
/*    This function extract and delete the PROMPT value in PSP	       */
/* --------------------------------------------------------------------*/
extract_prompt()
{
  char far *pr_pointer;
  char far *env_tmp;
  char *x;

/* in the PSP segment each variable is separated by a NULL caracter */
/* two NULL character follows the end of the last variable.	    */

/* This first loop scans PSP 'till it founds the PROMPT string      */
/* or 'till reaches the end (\0\0)                                  */

  env_tmp = env;

  do
  {
	 pr_pointer = strstr(env_tmp,"PROMPT=");
	 if (pr_pointer == NULL)
	 {
	      size -= strlen (env_tmp) + 1;
	      env_tmp = strrchr (env_tmp,'\0');
	      env_tmp++;
	 }
  } while ( *env_tmp != '\0' && pr_pointer == NULL );

  if (pr_pointer != NULL)			/* if PROMPT present in PSP ...*/
  {
	pr_pointer += 7;
	strcpy (&full[0],pr_pointer);		/* copy from the equal sign to \0 */
	x = strstr(&full[0], &due[0]);
	if (x != NULL)
		size += (x - &full[0]) + 13 ;
	size -= strlen (pr_pointer) + 8;
	pr_pointer = strrchr(pr_pointer,'\0');      /* move to the end of the string */
	pr_pointer++;				     /* move tho the next variable */
	while ((*pr_pointer != '\0') || (*(pr_pointer - 1) != '\0'))
	{
		*env_tmp = *pr_pointer;
		env_tmp++;
		pr_pointer++;
		size--;
	}
	*env_tmp = '\0';
  }
  else
	full[0] = '\0';	/* if NO PROMPT found in PSP */
  size--;
  env = env_tmp;
}

/* --------------------------------------------------------------------*/
/*  This function writes the fortune inside the PROMPT variable        */
/* --------------------------------------------------------------------*/
write_in_psp()
{
  char far *env_tmp;
  char *w;

  env_tmp = env++;

  strcat(env_tmp,"PROMPT=");
				/* put the first escape sequence */
  strcat(env_tmp,&uno[0]);
				/* add the fortune */
  strcat(env_tmp,&text[0]);
				/* now append the ending escape sequence */
  strcat(env_tmp,&due[0]);
				/* There was already a fortune in PROMPT? ... */
  w = strstr(&full[0],&due[0]);
  if (w == NULL)
  {
						    /* ...NO!	*/
	strcat (env_tmp, &full[0]);
	if (strlen (&full[0]) == 0)  strcat (env_tmp, "$p$g");
  }
  else
						   /* ....Yes!	*/
  {
	w = w + 13;
	if (*w != '\0') strcat (env_tmp,w);
  }
  env_tmp = strrchr(env_tmp,'\0');            /* move to the end of the string */
  *++env_tmp = '\0';
}

/* --------------------------------------------------------------------*/
/*    ...display the string					       */
/* --------------------------------------------------------------------*/
disp_string()
{
  printf ("%s\n",text);
}

/* --------------------------------------------------------------------*/
/*    reset PROMPT variable				*/
/* --------------------------------------------------------------------*/
reset_pr()
{
	strcat (env,"PROMPT=");
	strcat (env,&full[0]);
	*((strrchr (env,'\0')) + 1) = '\0';
	printf ("\nOut of environment space!\n");
	printf ("\nThe current environment space is %d bytes\n",full_size);
	printf ("\nyou should specify in your CONFIG.SYS file a SHELL\n");
	printf ("with at list %d bytes (/E:xxx parameter).\n",full_size - size + 123);
  	exit(1);
}

/* --------------------------------------------------------------------*/
/*    ...usage...						       */
/* --------------------------------------------------------------------*/
disp_usage()
{
  printf ("%s\n",version);
  printf("\n\t4Tune [Filespec] [/p] [/o]\n");
  printf("\nSwitches:\n");
  printf("\t[/p] Write fortune in PROMPT");
  printf("\n\t[/o] Display useful values\n");
  exit (1);
}

