// HOW TO COMPILE ME:   g++ chvtbl.C -o chvtbl
// setuidable chvt+screenblank 

// This code is placed in the public domain, with NO WARRANTY OF ANY
// KIND.  Go nuts.
//
// Welcome to another fine
//    This-cannot-be-the-right-solution(tm)
//   Instocode Product from ackleyshack.com.

// THIS CODE RELIES ON:
// tpctl:  http://tpctl.sourceforge.net/
//   Tested with tpctl-4.4 on RedHat 9

// Thu Jun 12 12:20:34 2003 ackley@: v0.0 Created

#include <unistd.h>     /* for execl */
#include <stdlib.h>     /* for exit */
#include <errno.h>      /* for errno */
#include <string.h>     /* for strerror */
#include <fcntl.h>      /* for open, O_RDONLY */
#include <sys/ioctl.h>  /* for ioctl */
#include <linux/vt.h>   /* for VT_ACTIVATE, VT_WAITACTIVE */
#include <iostream>

using namespace std;

static void ProcessArgs(int argc, char **argv) ;
static void Setup() ;
static void DoWork() ;
static void Usage(char * progname) ;

static int destvt = 1;          // Where to go
static bool tox = false;        // Whether we're going to x or from x
static int ttyfd;               // File description to ioctl on

int main(int argc, char ** argv)
{
  ProcessArgs(argc,argv);
  Setup();
  while (1) {
    DoWork();
  }
}

void ProcessArgs(int argc, char **argv)
{
  char * prog = argv[0];
  if (--argc > 0) {
    int vt = atoi(*++argv);
    if (vt<0) {
      tox = true;
      vt = -vt;
    }
    if (vt<1 || vt>10) Usage(prog);
    destvt = vt;
  }
  if (--argc > 0) Usage(prog);
}

void Usage(char * progname)
{
  cerr << "Usage: " << progname << " [vtnumber]" << endl;
  exit(1);
}

void Setup()
{
  ttyfd = open("/dev/console", O_RDONLY);
  if (!ttyfd) {
    cerr << "open tty failed: " << strerror(errno) << endl;
    exit(1);
  }
  if (tox) {
    cout << "\fHit <Enter> to chvt to vt" << destvt << endl;
  }
}

void DoWork()
{
  if (tox) {                    // Wait for an enter
    while (1) {
      char c = 0;
      cin.get(c);
      if (c == '\n')
        break;
      else
        cout << "got (" << (int) c << ")";
    }
  }
  if (ioctl(ttyfd, VT_ACTIVATE, destvt)) {
    cerr << "vt switch failed: " << strerror(errno) << endl;
    exit(2);
  }
  if (ioctl(ttyfd, VT_WAITACTIVE, destvt)) {
    cerr << "vt wait active failed: " << strerror(errno) << endl;
    exit(3);
  }

  if (!tox) {
    execl("/usr/bin/tpctl","/usr/bin/tpctl","--S",0);
    exit(errno);
  }
}


