
/* ********************************************************************* */
/* *                                                                   * */
/* * Copyright (c) 2006-2010, Dirk Krause                              * */
/* * All rights reserved.                                              * */
/* *                                                                   * */
/* * Redistribution and use in source and binary forms,                * */
/* * with or without modification, are permitted provided              * */
/* * that the following conditions are met:                            * */
/* *                                                                   * */
/* * * Redistributions of source code must retain the above            * */
/* *   copyright notice, this list of conditions and the               * */
/* *   following disclaimer.                                           * */
/* * * Redistributions in binary form must reproduce the above         * */
/* *   opyright notice, this list of conditions and the following      * */
/* *   disclaimer in the documentation and/or other materials          * */
/* *   provided with the distribution.                                 * */
/* * * Neither the name of the Dirk Krause nor the names of            * */
/* *   contributors may be used to endorse or promote                  * */
/* *   products derived from this software without specific            * */
/* *   prior written permission.                                       * */
/* *                                                                   * */
/* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND            * */
/* * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,       * */
/* * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF          * */
/* * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE          * */
/* * DISCLAIMED.                                                       * */
/* * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE          * */
/* * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,             * */
/* * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT           * */
/* * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;          * */
/* * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)          * */
/* * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN         * */
/* * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE         * */
/* * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS           * */
/* * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH              * */
/* * DAMAGE.                                                           * */
/* *                                                                   * */
/* ********************************************************************* */

#line 36 "edbp.ctr"




/**	@file	edbp.c	The edbp program.
*/



#include <stdio.h>

#include <dk.h>

#if DK_HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if DK_HAVE_STDLIB_H
#include <stdlib.h>
#endif
#if DK_HAVE_UNISTD_H
#include <unistd.h>
#endif
#if DK_HAVE_SIGNAL_H
#include <signal.h>
#endif
#if DK_HAVE_STRING_H
#include <string.h>
#endif
#if DK_HAVE_STRINGS_H
#include <strings.h>
#endif

#include <dksignal.h>


#line 70 "edbp.ctr"




/**	Flag: Can continue.
*/
static
#if DK_HAVE_VOLATILE
volatile
#endif
int cc = 1;


/**	SIGHUP handler.
	@param	signo	Signal number (SIGHUP).
*/
dk_signal_ret_t
handler_sighup DK_P1(int, signo)
{
  dksignal_refresh(signo, handler_sighup);
  cc = 0;
  fprintf(
    stderr,
    "SIGHUP received.\n"
  ); fflush(stderr);
}



/**	SIGINT handler.
	@param	signo	Signal number (SIGINT).
*/
dk_signal_ret_t
handler_sigint DK_P1(int, signo)
{
  dksignal_refresh(signo, handler_sigint);
  cc = 0;
  fprintf(
    stderr,
    "SIGINT received.\n"
  ); fflush(stderr);
}



/**	SIGTERM handler.
	@param	signo Signal number (SIGTERM).
*/
dk_signal_ret_t
handler_sigterm DK_P1(int, signo)
{
  dksignal_refresh(signo, handler_sigterm);
  cc = 0;
  fprintf(
    stderr,
    "SIGTERM received.\n"
  ); fflush(stderr);
}



/**	SIGPIPE handler.
	@param	signo	Signal number (SIGPIPE).
*/
dk_signal_ret_t
handler_sigpipe DK_P1(int, signo)
{
  dksignal_refresh(signo, handler_sigpipe);
  cc = 0;
  fprintf(
    stderr,
    "SIGPIPE received.\n"
  ); fflush(stderr);
}



/**	The buffer to store the bit patterns.
*/
static char buffer[16384];


/**	Size of buffer.
*/
static size_t sz_buffer = sizeof(buffer);



/**	Buffer size for write operations.
*/
static size_t bs = 512;



/**	The pattern number.
	0 <= patno <= 7.
*/
static unsigned patno = 0;



/**	Fallback implementation of memset().
	@param	ptr	Destination buffer.
	@param	c	Byte.
	@param	sz	Size of \a ptr.
*/
static
void
my_memset DK_P3(char *,ptr, char,c, size_t,sz)
{
#if DK_HAVE_MEMSET
  memset((void *)ptr, c, sz);
#else
  char *cptr; size_t i;
  cptr = ptr;
  for(i = 0; i < sz; i++) { *(cptr++) = c; }
#endif
}



/**	The main() function of the edbp program.
	@param	argc	Number of command line arguments.
	@param	argv	Command line arguments array.
	@return	0 on success, any other value indicates an error.
*/
#if DK_HAVE_PROTOTYPES
int main(int argc, char *argv[])
#else
int main(argc, argv) int argc; char *argv[];
#endif
{
  unsigned newbs = 512;
  unsigned long ul1 = 0UL, ul2 = 0UL, ul3 = 0UL;
#ifdef SIGHUP
  dk_signal_disp_t disp_hup;
#endif
#ifdef SIGINT
  dk_signal_disp_t disp_int;
#endif
#ifdef SIGTERM
  dk_signal_disp_t disp_term;
#endif
#ifdef SIGPIPE
  dk_signal_disp_t disp_pipe;
#endif
  if(argc > 1) {
    if(sscanf(argv[1], "%u", &newbs) == 1) {
      patno = newbs;
      if(patno > 7) {
        patno = 7;
	fprintf(
	  stderr,
	  "ERROR: Pattern number must be in range 0 ... 7!\n"
	); fflush(stderr);
      }
    } else {
      fprintf(
        stderr,
	"ERROR: Pattern number must be in range 0 ... 7!\n"
      ); fflush(stderr);
    }
  }
  if(argc > 2) {
    if(sscanf(argv[2], "%u", &newbs) == 1) {
      bs = newbs;
      if(bs > sz_buffer) {
	fprintf(
	  stderr,
	  "ERROR: Blocksize must be in range 1 ... 16384!\n"
	); fflush(stderr);
	bs = sz_buffer;
      }
    } else {
      fprintf(
        stderr,
	"ERROR: Blocksize must be in range 1 ... 16384!\n"
      ); fflush(stderr);
    }
  }
  switch((int)patno) {
    case 7: {
      my_memset(buffer, (char)0xAA, sz_buffer);
    } break;
    case 6: {
      my_memset(buffer, (char)0x55, sz_buffer);
    } break;
    case 5: {
      my_memset(buffer, (char)0xCC, sz_buffer);
    } break;
    case 4: {
      my_memset(buffer, (char)0x33, sz_buffer);
    } break;
    case 3: {
      my_memset(buffer, (char)0xF0, sz_buffer);
    } break;
    case 2: {
      my_memset(buffer, (char)0x0F, sz_buffer);
    } break;
    case 1: {
      my_memset(buffer, (char)0xFF, sz_buffer);
    } break;
    case 0: {
      my_memset(buffer, (char)0x00, sz_buffer);
    } break;
  }
  cc = 1; ul1 = ul2 = ul3 = 0UL;
#ifdef SIGHUP
  disp_hup = dksignal_set(SIGHUP,handler_sighup);
#endif
#ifdef SIGINT
  disp_int = dksignal_set(SIGINT,handler_sigint);
#endif
#ifdef SIGTERM
  disp_term = dksignal_set(SIGTERM,handler_sigterm);
#endif
#ifdef SIGPIPE
  disp_pipe = dksignal_set(SIGPIPE,handler_sigpipe);
#endif
  while(cc) {
    if(write(1, buffer, bs) < bs) {
      cc = 0;
      fprintf(
        stderr,
	"ERROR: Failed to write %lu bytes!\n",
	(unsigned long)bs
      ); fflush(stderr);
    } else {
      ul1++;
      if(ul1 == 0UL) {
        ul2++;
	if(ul2 == 0UL) {
	  ul3++;
	}
      }
    }
  }
#ifdef SIGPIPE
  if(disp_pipe) { dksignal_set(SIGPIPE,disp_pipe); }
#endif
#ifdef SIGTERM
  if(disp_term) { dksignal_set(SIGTERM,disp_term); }
#endif
#ifdef SIGINT
  if(disp_int)  { dksignal_set(SIGINT,disp_int); }
#endif
#ifdef SIGHUP
  if(disp_hup) { dksignal_set(SIGHUP,disp_hup); }
#endif
  fprintf(
    stderr,
    "Finished after writing %lu:%lu:%lu blocks.\n", ul3, ul2, ul1
  ); fflush(stderr);
  exit(0); return 0;
}

