/* $Id: waiteject.c,v 1.7 2007/11/20 22:31:41 talon Exp talon $ */
/*This is a re-write of a similar C program written by Rob Strassburg
  I'm writing this version because I could not find his version online 
  and because I wanted make it support more than just Linux */
/* Credits: Rob Strassburg for the original idea.
	    William Schaub re-writing the concept from memory. */
/* This program is meant to be used in mass CD burning shell scripts
   it ejects the CD tray and then waits for a disc to be inserted before it
   returns. It will return a 0 on success and a 1 for failure.*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

/*OS Specific includes */
#ifdef LINUX
#include <linux/cdrom.h>
#endif
#ifdef SOLARIS
#include <sys/dkio.h>
#include <sys/vtoc.h>
#endif
void eject(int fd);
int main (int argc, char **argv)
{
	int fd;
	int ret;

	if(argc <= 1)
	{
		fprintf(stderr,"usage: waiteject /dev/cdromdevice\n");
		return 1;
	}
	
	/* Open the device and send an eject signal only if
	   the tray isnt already open, then block until a disc is seen 
	   in the drive */
	if((fd = open(argv[1],O_RDONLY|O_NDELAY))!= -1)
	{
		ret = check_status(fd);
		if(!ret)
		{
			eject(fd);
		}
		
		while(check_status(fd))
		{
			sleep(1);
		}
		return 0;
	}
	else { perror(argv[1]); return 1; }

	/* We should never reach here */
	fprintf(stderr,"Execution reached end of main, this should never happen!\n");
	return 1;
}

/* Issue OS specific ioctls to check the drive status
   returns 1 for ejected and 0 for inserted */
int check_status(int fd)
{
	/* Linux */
#ifdef LINUX
	int ret;
	ret = ioctl(fd,CDROM_DRIVE_STATUS,0);
	if(ret != CDS_DISC_OK || ret == CDS_TRAY_OPEN)
		return 1;
	else 
		return 0;
#endif
	/* Solaris */
#ifdef SOLARIS
	int state;
	int ret;
	struct dk_minfo info;
	state = DKIO_NONE;
	ret = ioctl(fd,DKIOCSTATE,&state);
	if(state == DKIO_EJECTED)
		ret = 1;
	if(state == DKIO_INSERTED)
		ret = 0;
#ifdef DEBUG
	fprintf(stderr,"state %d ret %d errno %d\n",state,ret,errno);
#endif
	return ret;
#endif
}

/* Issue OS Specific Eject ioctl */
void eject(int fd)
{
	/* Linux */
#ifdef LINUX
ioctl(fd,CDROMEJECT,0);
#endif

/* Solaris */
#ifdef SOLARIS
ioctl(fd,DKIOCEJECT,NULL);
#ifdef DEBUG
fprintf(stderr,"eject\n");
#endif
#endif
}

/*
$Log: waiteject.c,v $
Revision 1.7  2007/11/20 22:31:41  talon
Fix comments to reflect that it supports more than just linux now.

Revision 1.6  2007/11/20 22:26:53  talon
append all log entries

Revision 1.5  2007/11/20 22:17:18  talon
Really add RCS log to source
 
revision 1.4
date: 2007/11/20 22:14:31   talon
added rcs log key

revision 1.3
date: 2007/11/20 22:12:36   talon
Added basic solaris support that seems to work.

revision 1.2
date: 2007/11/20 18:33:01;  talon
Start of portability changes, the Linux code works but the Solaris code is
still a work in progress.

revision 1.1
date: 2007/11/19 18:45:41   talon
Initial revision

*/

