/*
 * cipher.c
 * This program reads an input file and enciphers (or deciphers) it, using
 * cumulative xor on its characters.
 */

#include <stdio.h>
#include <string.h>

#define MAX_NAME 80

int main (int argc, char **argv)
{
  FILE   *p_infile;           /* The input file. */
  char   out_name[MAX_NAME];  /* The name of the output file. */
  char   *p_suffix;           /* The location of the ".xxx" suffix. */
  FILE   *p_outfile;          /* The output file. */
  int    c;                   /* The current character read. */
  int    cum_xor;             /* Cummulative xor of all characters so far. */
  int    is_ciphered;         /* Is the input file enciphered. */

  /* Check the number of arguments to the program: */
  if (argc < 2)
  {
    printf ("Usage: %s <input file>\n", argv[0]);
    return (1);
  }

  /* Open the input file, specified by argv[1], in binary mode. */
  p_infile = fopen (argv[1], "rb");

  if (p_infile == NULL)
  {
    printf ("Failed to open the input file '%s'.\n", argv[1]);
    return (1);
  }

  /* If the input file name has a ".xxx" suffix, it is enciphered and we should
     decipher it. Otherwise, we should encipher it. */
  if ((p_suffix = strstr (argv[1], ".xxx")) != NULL)
  {
    /* Cut the ".xxx" suffix to produce the output filename. */
    strncpy (out_name, argv[1], p_suffix - argv[1]);
    out_name[p_suffix - argv[1]] = '\0';

    is_ciphered = 1;
  }
  else
  {
    /* Append the ".xxx" suffix to produce the output filename. */
    strcpy (out_name, argv[1]);
    strcat (out_name, ".xxx");

    is_ciphered = 0;
  }

  /* Open the output file in binary mode. */
  p_outfile = fopen (out_name, "wb");

  if (p_outfile == NULL)
  {
    printf ("Failed to open the output file '%s'.\n", out_name);
    fclose (p_infile);
    return (1);
  }

  /* Read the input characters one by one. */
  cum_xor = 0;
  while ((c = fgetc(p_infile)) != EOF)
  {
    /* Modify the character by xoring it with the cummulative xor so far. */
    c = c ^ cum_xor;

    /* Write it to the output file. */
    fputc (c, p_outfile);

    /* Update the cummulative xor of the unciphered characters. */
    if (is_ciphered)
      cum_xor = cum_xor ^ c;
    else
      cum_xor = c;
  }

  printf ("The file '%s' was successfully %s,\noutput was written to '%s'.\n",
          argv[1],
          is_ciphered ? "deciphered" : "enciphered",
          out_name);

  /* Close the file. */
  fclose (p_infile);
  fclose (p_outfile);

  return (0);
}

