/* Prints "yes" repeatedly but slowly.
   Copyright (C) 1998  Barak Pearlmutter <bap@cs.unm.edu>
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* To do:
 *
 * use dithering to sleep the right amount of time despite rounding.
 *
 * read time every once in a while, and use realtime to compensate in
 * case i/o or other time sinks are significant.  (This could also be
 * done using threads.)
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>

typedef enum {false=0, true=1} bool;


void
usage(int argc, char **argv)
{
  printf("\
Print `yes' or given string over and over, at a rate given by the user.

   usage: %s [options...] [string]

   options
	--help		This message
	--version	print version information and exit
	--rate n	lines/sec (default = 500)
	--max m		maximum number of lines to print
	--no-flush	don't fflush(stdout) after each line\n",
	 argv[0]);
}


int
main(int argc, char **argv)
{
  long t;			/* time to usleep between lines */
  long n = 500;			/* default lines/sec rate */
  int m = -1;			/* -1 means forever */
  bool flush = true;		/* flush stdout after each line? */
  char *what = "yes";		/* text to print on each line */

  while (1)
    {
      static struct option long_options[] =
      {
	{"help", 0, 0, 'h'},
	{"version", 0, 0, 'v'},
	{"rate", 1, 0, 'r'},
	{"max", 1, 0, 'm'},
	{"no-flush", 0, 0, 'f'},
	{0,0,0,0}
      };
      int option_index = 0;
      int c = getopt_long_only(argc, argv, "",
			       long_options, &option_index);
      if (c == -1) break;
      switch (c)
	{
	case 0:
	  printf ("option %s", long_options[option_index].name);
	  if (optarg)
	    printf (" with arg %s", optarg);
	  printf ("\n");
	  break;

	case 'h':
	  usage(argc, argv);
	  return 0;
	case 'v':
	  printf("syes (BAP hack) cautious yea-sayer 1.0\n");
	  exit(0);
	case 'r':
	  {
	    char *endptr;
	    n = strtol(optarg, &endptr, 0);
	    if (*endptr != '\0' || errno) {
	      fprintf(stderr, "error: invalid rate `%s'\n", optarg);
	      exit(2);
	    }
	  }
	  break;
	case 'm':
	  {
	    char *endptr;
	    m = strtol(optarg, &endptr, 0);
	    if (*endptr != '\0' || errno || m <= 0) {
	      fprintf(stderr, "error: invalid number `%s'\n", optarg);
	      exit(2);
	    }
	  }
	  break;
	case 'f':
	  flush = false;
	  break;

	case '?':
	  exit(1);

	default:
	  printf ("?? getopt returned character code 0%o ??\n", c);
	}
    }

  if (optind+1 == argc)
    what = argv[optind];
  else if (optind < argc) {
    fprintf(stderr, "%s: too many arguments.\n", argv[0]);
    exit(2);
  }

  t = 1000000.0 / n;

  while (m == -1 || m--) {
    puts(what);
    if (flush) fflush(stdout);
    if (t) usleep(t);
  }
  return 0;
}

