
#include <iostream.h>

extern "C"
{
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
};

//$Id: sw.cc, v 1.3 1994 / 09 / 12 05: 57:56 root Exp root $
//
//$Log:sw.cc, v $
// Revision 1.3 1994 / 09 / 12 05: 57:56 root
// ***empty log message ***
//
//Revision 1.2 1994 / 09 / 12 05: 37:40 root
// multithreaded
//
//Revision 1.1 1994 / 09 / 12 05: 06:39 root
// Initial revision
//
//Revision 1.3 1994 / 09 / 11 20: 03:39 root
// ***empty log message ***
//
//Revision 1.2 1994 / 09 / 11 20: 00:44 root
// ***empty log message ***
//
//Revision 1.1 1994 / 09 / 11 19: 42:41 root
// Initial revision
//


enum
{
  volume,
  size,
  blocks,
  maxnames = 16,
  sw_max_task = 32
};

const char *_Name[] =
{
  "sw_create",
  "sw_write",
  "sw_fsync",
  "sw_seek",
  "sw_tail",
  "sw_close",
  "sw_sync",
  "sw_activate",
  "sw_end",
  "swapbuild._Name._tempfile",
  "_end"
};
enum
{
  sw_create,
  sw_begin = sw_create,
  sw_write,
  sw_fsync,
  sw_seek,
  sw_tail,
  sw_close,
  sw_sync,
  sw_activate,
  sw_end,
  _tempfile,
  _end
};

typedef struct _bod
{

  char *NameTemplate[maxnames];
  char *signature;

  int TotalM, FileK, currnm;

}

bod;


bod *Getopt (int argc, char *argv[]);
void Getarg (char *t, int state, bod * bod);
int main (int argc, char *argv[]);



int
main (int argc, char *argv[])
{

  bod *prime = Getopt (argc, argv);


  if (prime->TotalM && prime->FileK)
    {
      char t[1024];

      for (int state = 0; state < 2; state++)
	{
	  switch (state)
	    {
	    case 0:
	      {
		sprintf (t, ">%s", _Name[_tempfile]);
		break;
	      };
	    case 1:
	      {
		sprintf (t, "/sbin/mkswap %s %d", _Name[_tempfile], prime->FileK);
		break;
	      };
	    };

	  if (system (t))
	    return -1;
	};
    };

  prime->signature = new char[4096];

  {
    int f = open (_Name[_tempfile], O_APPEND | O_RDONLY);

    read (f, prime->signature, 4096);
    close (f);

    //unlink (_Name[_tempfile]);
  };

  int rows = prime->currnm;
  cout << "rows =" << (int) rows << "\n";

  int col;
  cout << (int) (col = (prime->TotalM * 1024 * 1024));
  cout << (int) (col /= (prime->FileK * 1024));
  cout << (int) (col /= (rows));
  cout << "col =" << (int) col << "\n";

  char *NameList[rows][col];
  int fxp[rows][col];

  for (int state = sw_begin; state < sw_end; state++)
    {
      for (int j = 0; j < col; j++)
	{
	  for (int k = 0; k < rows; k++)
	    {
	      static int pole;
	      switch (state)
		{
		case sw_create:
		  {

		    char *n = prime->NameTemplate[k];
		    char *n1 = alloca (1024);

		    cout << n << "---->";

		    sprintf (n1, "%s%d.%d", n, k, j);

		    cout << n1 << "\n";

		    NameList[k][j] = strdup (n1);

		    cout << NameList[k][j];

		    int f = open (n1,
				  O_WRONLY |
				  O_TRUNC |
				  O_CREAT |
				  O_NONBLOCK
		    );

		    fxp[k][j] = f;

		    break;
		  }

		case sw_write:
		  {
		    int _t;
		    if (pole < sw_max_task)
		      {
			_t = fork ();

			if (_t)
			  pole++;

			break;
		      };

		    cout << write (fxp[k][j],
				   prime->signature,
				   prime->FileK * 1024);
		    if (!_t)
		      {
			pole--;
			exit (0);
		      };
		    break;
		  };
#if 0
		case sw_fsync:
		  {
		    cout << fsync (fxp[k][j]);
		    break;
		  };

		case sw_seek:
		  {
		    cout << lseek (fxp[k][j],
				   prime->FileK * 1024 - 1,
				   SEEK_SET);
		    break;
		  };
		case sw_tail:
		  {
		    cout << write (fxp[k][j], prime->signature, 1);
		    break;
		  };
#endif
		case sw_close:
		  {
		    if (pole)
		      wait (NULL);
		    cout.flush ();

		    cout << close (fxp[k][j]);
		    break;
		  }

		case sw_sync:
		  {
		    sync ();
		    goto cheat;
		    break;
		  };

		case sw_activate:
		  {
		    swapon (NameList[k][j]);
		    break;
		  };
		};

	      //cout << ".";
	    };
	};
    cheat:
      cout << "State " << _Name[state] << "\n";
    };
};

bod *
Getopt (int argc, char *argv[])
{
  bod *prime = new bod;

  prime->currnm = 0;


  int state = volume;

  for (int carg = 1; carg < argc; carg++)
    {
      char *t = argv[carg];

      switch (*t)
      case '-':
	{
	  switch (t[1])
	    {
	    case 'v':
	      {
		state = volume;
		break;
	      };
	    case 's':
	      {
		state = size;
		break;
	      };
	    case 'b':
	      {
		state = blocks;
		break;
	      };
	    };

	  t += 2;
	  break;
	};


      if (!isspace (*t) && *t)
	(void) Getarg (t, state, prime);
      cout << "arg #" << carg << "=" << argv[carg] << "\n";
    };

  return prime;
};

void
Getarg (char *t, int state, bod * prime)
{

  switch (state)
    {

    case volume:
      {
	prime->NameTemplate[prime->currnm] = strdup (t);
	prime->currnm++;
	cout << "v";
	break;
      };

    case size:
      {
	cout << (int) (prime->TotalM = atoi (t)) << "s";
	cout << prime->TotalM;
	break;
      };

    case blocks:
      {
	cout << (int) (prime->FileK = atoi (t)) << "b";
	break;
      };
    };
};
