The presence of errors in software development (and not only) is inevitable. However, over time the programs improve and tend to perfection through various techniques and methods we have developed.

The deterministic problems are easy to spot because they always lead to the same error. There are tools that run through the source code of an application to find possible deterministic errors (these tools are especially useful in applications written with scripting languages such as Python, Bash Scripting, etc).

Many times, however, the problems are not deterministic and are difficult to reproduce or to identify because what is of great significance now is the condition of both the program and the rest of the environment. The reasons leading a program to non-deterministic errors can be many. Yet, it is usually due to undesirable data entering or user action.

To be able to reproduce a non-deterministic error requires recording of the program status each time it is in critical areas (e.g. data input by the user) so then to identify the error with the appropriate study. Several applications follow this tactic today.

Below we quote a simple but quite comprehensive and extended version of the function ‘fgets’ of the standard C library which besides the common function allows recording of data entered by the end user to backup and data extraction from an older snapshot of interaction between user – application.

In this way we are recording a backup of the user data at the entry and can also possibly reproduce non-deterministic errors encountered by the relevant data.

/*
 *  xfgets.c -- version of fgets() that allows playback and recording.
 *
 *  Copyright (C) 2007  Efstathios Chatzikyriakidis (stathis.chatzikyriakidis@gmail.com)
 *
 *  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 3 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, see <http://www.gnu.org/licenses/>.
 */

/* include standard headers. */
#include <stdio.h>

FILE * save_file = NULL; /* save input in this file. */
FILE * play_file = NULL; /* playback data from this file. */

/********************************************************
 * xfgets -- get a line from the input file and         *
 *           record it in a save file if needed         *
 *                                                      *
 * parameters:                                          *
 *      line -- the line to read                        *
 *      size -- maximum number of characters to get     *
 *      file -- file to get data from (normally stdin)  *
 *                                                      *
 * returns:                                             *
 *      `NULL' when error/EOF in read or `result' line  *
 ********************************************************/
char *
xfgets(char * line, int size, FILE * file)
{
  extern FILE * save_file; /* file to save strings in. */
  extern FILE * play_file; /* file for alternate input. */

  char * result = NULL; /* result of fgets(). */

  /* if there is a playback file. */
  if (play_file != NULL)
  {
    /* get the line from the file. */
    result = fgets(line, size, play_file);

    /* echo the input to the standard out so the user sees it. */
    fputs(line, stdout);
  }
  else
    /* get the line normally. */
    result = fgets(line, size, file);

  /* if there is a save file. */
  if (save_file != NULL)
    fputs(line, save_file); /* save the line in the file. */

  /* return either a line or NULL. */
  return (result);
}