/*
Filename: IO.CPP
Purpose: Grant hardware port access rights to a user-written program
Date: Monday 17 October 2005
Author: Chris Carter, chris.carter@iee.org
Usage: ./io ./<user-program-name> <parameters>
*/

// Header files

#include <iostream>			// For 'cout'
#include <cstdio>			// C++ wrapper for 'stdio.h', needed for 'perror'
#include <unistd.h>			// C library needed for 'ioperm', 'setgid', etc. (libc5)
#include <sys/io.h>			// C library needed for 'ioperm' (glibc)
#include <sys/resource.h>	// C library needed for 'setpriority', etc.

// Use enumeration rather than #define in C++

enum
{
	lp0_base_addr = 0x378,	// Define the base address of the first parallel port (in hex)
	lp_length = 3			// Define the number of register bytes that should be set, above
							// the base address
};

using namespace std;

// Start of the main function

int main(int argc, char *argv[])
{
	if (argc < 2)	// Check if the user supplies the name of a program to execute
	{
		cout << "You must supply the name of a program to run!" << endl;
		exit(-1) ;
	}

// Sets the process execution priority ('niceness'). Negative values increase the
// priority, positive values decrease it, zero is the default.
// See: man getpriority

	setpriority(PRIO_PROCESS, 0, 0);

// Gain access to the port(s) and REMOVE the root privilege by setting the port
// access permission bits to '1'.

	if (ioperm(lp0_base_addr, lp_length, 1))
	{
		perror("Attempt to change permissions on port lp0 failed");
		exit(-1);
	}

// Change the Group and User IDs of this program

	setgid(getgid());	// Sets the Group ID of the current process
	setuid(getuid());	// Sets the User ID of the current process

// Replace the current running program image ('io') with another one.
// argv[1] is the name of the program supplied by the user

	execvp(argv[1], &argv[1]);
	
// If 'execvp' succeeded, we will never execute anything past this point!

    perror("Unable to execute the user program");
    cout << "Execution of " << argv[1] << " failed." << endl;
    exit(-1) ;
}

// End of file.
