Listing 3 Keeping a state in a structure

enum File_state { UNOPENED, BUFFER_ALLOCATED, FILE_OPEN,
RECORD_READ};
char * File_state_strings[] = {"Unopened", "Buffer allocation",
"File open", "File reading"};

typedef struct
   {
   enum File_state state;  // Current state of file
   int file_id;    // Id from open
   char *buffer;   // Buffer for read
   } File;

int File_initialize(File * file, char *filename, char *purpose);
void File_terminate(File * file);

#define SUCCESS 1
#define FAILURE 0

main()
   {
   File file;
   int return_code;
   if (File_initialize(&file, "filename", "purpose") == SUCCESS)
      {
      return_code = 0;
      /* Do whatever required */
      }
   else
      return_code = 1;
   File_terminate(&file);
   exit(return_code);
   }

int File_initialize(File * file, char *filename, char *purpose)
   {
   int read_count;
   int return_code = FAILURE;
   file->state = UNOPENED;
   if (Buffer_initialize(&file->buffer, BUFSIZ, "file buffer")
      == SUCCESS)
      file->state = BUFFER_ALLOCATED;
   if (file->state == BUFFER_ALLOCATED)
      {
      file->file_id = open(filename, 0_RDONLY);
      if (file->file_id >= 0)

         file->state = FILE_OPEN;
      }
   if (file->state == FILE_OPEN)
      {
      read_count = read(file->file_id, file->buffer, BUFSIZ);
      if (read_count > 0)
         {
         file->state = RECORD_READ;
         return_code = SUCCESS;
         }
      }
   if (return_code != SUCCESS)
      fprintf(stderr, "Filename %s purpose %s error at %s",
         filename, purpose, File_state_strings[file->state]);
   return return_code;
   }

void File_terminate(File * file)
   {
   /*** Maintenance note - fall through required ***/
   switch(file->state)
      {
   case RECORD_READ:
   case FILE_OPEN:
      close(file->file_id);
   case BUFFER_ALLOCATED:
      Buffer_terminate(&file->buffer);
   case UNOPENED:
      break;
   default:
      fprintf("Error in File_terminate -- illegal state");
      }
   return;
   }

/* End of File*/