/*  chkyorn.c:	  Prompts the user for an answer (y/n)
|*  Writen By:    Matthew Long (long1@eng.auburn.edu)
|*  Date:	  3/20/91
|*  Modified:	  12/4/92 	to conform more to the SYS V version
|*  Modified By:  Hunter Eidson (eeidson@eng.auburn.edu)
|*  Date:         4/08/91
|*  usage:	  ckyorn [-Q][-d "default"[-t "time"]][-p "prompt"] 
|*  parameters:
|*  argc	  The command line argument count
|*  argv	  Pointer to array of arguments
|*  -Q		  Disallow user termination
|*  -t            Specifiy time before time-out
|*  -d		  Specify the default response
|*  -p		  Specify the prompt string
|*  returns:
|*  0		  sucessful operation
|*  1		  EOF in input  
|*  2		  usage error
|*  3		  user quit
*/

#ifndef lint
static char SCCS_id[] = "@(#)ckyorn.c   1.3   2/1/93   Auburn University Engineering";
#endif

#include <stdio.h>
#include <errno.h>
#include <sys/termios.h>
#include <signal.h>
#define bool         char
#define TRUE         (1)
#define FALSE        (0)
#define DEFAULT_PROMPT "Yes or No"
#define VALID_OPS "Qht:d:p:"
#define MAX_STRING_LEN 70
#define SUCCESS_TERM 0
#define EOF_TERM     1
#define USER_TERM    3
#define USAGE_TERM   2
#define AFIRMATIVE  "y"
#define NEGATIVE    "n"
#define DEFAULT_ERROR "ERROR - Please enter yes or no.\n"
#define DEFAULT_HELP "\tTo respond in the affirmative, enter y, yes, Y, or YES. To respond in\n\tthe negative, enter n, no, N, or NO.\n"

void process_switches();
void prompt_user();
int  validate_response();
int  get_response();
int  quit_signal();

/*  assume that no command line options are used */
int  no_quit=FALSE,
     wait_for_inp=TRUE,
     no_default=TRUE,
     use_default_prompt=TRUE,
     time_to_wait;
char response[ MAX_STRING_LEN ],
     cr_response[ MAX_STRING_LEN ],
     prompt_string[ MAX_STRING_LEN ];



/*  main():	Main procedure
|*  usage:	main(argc,argv)
|*  this is the main function its job is to call all the other functions
*/


void main(argc,argv)
   int 	argc;
   char	*argv[];
{
   int	valid=FALSE;

/*  signal handlers for user quit */
(void)signal( SIGHUP, quit_signal);
(void)signal( SIGINT, quit_signal);
(void)signal( SIGQUIT, quit_signal);
(void)signal( SIGTSTP, quit_signal);

cr_response[0] = '\0';
process_switches(argc,argv);
if ( use_default_prompt )
   {
   (void) strcpy(prompt_string,DEFAULT_PROMPT);
   }
while ( !valid )
{
   prompt_user(prompt_string);
   get_response(response);
   valid = validate_response(response);
}
fprintf(stdout,"%s\n",response);
exit ( SUCCESS_TERM );
}


/*  quit_signal:		what to do if a user ^c etc.
|*  usage:	called automatically on signal
|*  parameters:
|*  sig		    
|*  code
|*  scp
|*  addr
|*  returns:
|*  USER_TERM		exits the program w/ exit ( 2)
*/

int quit_signal( sig, code, scp, addr)
   int sig,code;
   struct sigcontext *scp;
   char *addr;
{
if ( !no_quit )
   exit ( USER_TERM );
}

/*  process_switches():		parses the command line arguments
|*  usage:	process_swithes(argc,argv)
|*  parameters:
|*  argc	argument count
|*  argv	argument list
|*  VALID_OPS	string containing the valid arguments(global macro)
|*  returns:
|*  void	the function is void
|*  cr_response	carriage return default response(global)
|*  prompt_string	The string to be used as a user prompt(global)
*/

void process_switches(argc,argv)
   int	argc;
   char	*argv[];
{
   extern	char	*optarg;
   extern	int	optind;
	        int	flag;

while ( (flag=getopt(argc,argv,VALID_OPS)) != -1 )
switch ( flag )
{
   case 'Q':
      no_quit = TRUE;
      break;
   case 'd':
      strcpy(cr_response,optarg);
      no_default = FALSE;
      break;
   case 'p':
      strcpy(prompt_string,optarg);
      use_default_prompt = FALSE;
      break;
   case 't':
      time_to_wait = atoi(optarg);
      wait_for_inp = FALSE;
      break;
   case 'h':
   default:
      fprintf(stderr, "Usage: ckyorn [options]\nwhere options may include:\n\t-Q  #quit not allowed\n\t\t-d default\n\t-p prompt\n");
      exit ( USAGE_TERM);
      break;
}
if ((wait_for_inp == FALSE)&&(no_default == TRUE)) {
    fprintf(stderr, "Usage: ckyorn [options]\nwhere options may include:\n\t-Q  #quit not allowed\n\t\t-d default\n\t-p prompt\n");
    exit ( USAGE_TERM);
    }
}

/*  prompt_user():	Writes the prompt string to *stderr*(not stdout)
|*  usage:	prompt_user(prompt_string)
|*  parameters:
|*  prompt_string	This is the string to be used
|*  returns:
|*  void
*/

void prompt_user(prompt_string)
   char	prompt_string[ MAX_STRING_LEN ];
{
fprintf(stderr,"\n%s",prompt_string);
if (no_quit)
   fprintf(stderr, " [y,n,?] ");
else
   fprintf(stderr, " [y,n,?,q] ");
}

/*  get_response():	Gets users respons from stdin
|*  usage:	get_response(response_string)
|*  parameters:	
|*  none	function only returns response_string
|*  returns:
|*  response_string	this is what the user entered
*/

int get_response(response_string)
   char	response_string[ MAX_STRING_LEN ];
{
   struct termios  tbuf;
   char input;

if ( wait_for_inp == FALSE ) 
  {
    if (ioctl (0, TCGETS, &tbuf))
      perror("ioctl TCGETS failed");
    tbuf.c_lflag ^= ICANON;
    tbuf.c_cc[VMIN] = (char) 0;
    tbuf.c_cc[VTIME] = (char) (10*time_to_wait);
    if (ioctl (0, TCSETS, &tbuf))
      perror("ioctl TCSETS failed");
  }

if ( fgets(response_string,MAX_STRING_LEN,stdin) != NULL)
  {
    strtok(response_string,"\n");
    return( 0 );
  }
else
  {
    if (wait_for_inp == FALSE) 
      {
	response_string[0] = '\n';
	return( 0 );
      }
    else
      {
	exit ( EOF_TERM);
      }
  }

if ( wait_for_inp == FALSE )
  {
    tbuf.c_lflag ^= ICANON;
    tbuf.c_cc[VMIN] = (char) 4;
    tbuf.c_cc[VTIME] = (char) 0;
    if (ioctl (0, TCSETS, &tbuf))
      perror("ioctl TCSETS failed");
  }
}
   
/*  validate_response():	checks users input for validity
|*  usage:	validate(response)
|*  parameters:
|*  response	the users input
|*  returns:
|*  1		if users input is valid
|*  0		if users input is invalid
|*  exit (USER_TERM)	if the user enters q or quit
|*  response	return string defined by AFIRMATIVE or NEGATIVE or the
|*		invalid input
*/

int validate_response(response)
   char response[ MAX_STRING_LEN ];
{
if ( response[0] == '\n' )
   strcpy(response,cr_response);
if ( !strcasecmp(response,"yes") )
   {
   strcpy(response,AFIRMATIVE);
   return ( TRUE);
   }
else if ( !strcasecmp(response,"no") )
   {
   strcpy(response,NEGATIVE);
   return ( TRUE);
   }
else if ( !strcasecmp(response,"y") )
   {
   strcpy(response,AFIRMATIVE);
   return ( TRUE);
   }
else if ( !strcasecmp(response,"n") )
   {
   strcpy(response,NEGATIVE);
   return ( TRUE);
   }
else if ( !strcmp(response,"?") )
   {
   fprintf(stderr,DEFAULT_HELP);
   return ( FALSE );
   }
else if ( *response == 'q' )
   {
   if ( !no_quit )
      fprintf(stdout,"q");
      exit( USER_TERM);
   return( FALSE);
   }
else if ( !strcmp(response,"quit") )
   {
   if ( !no_quit )
      fprintf(stdout,"q");
      exit( USER_TERM);
   return( FALSE);
   }
else
   {
   fprintf(stderr,DEFAULT_ERROR);
   return( FALSE);
   }
}
