/*
   This program can terminate spool jobs, release locks, 
   and rescind writeownership.
*/
 
#define ver 1
#define rev 0
#define mod 'a'
#define asm ' '

#include "release.os"
#include "c:switch.os"
#include "d:mpstruct.def"

#define  UNASSIGNED  0xFF	/* Unit code for unassigned drive number */
#ifdef cpm80
#define  MESACK	     0x4d
#else 
#define  MESACK      0x00	/* Ack code for write mode command */
#endif
#define  NOT_OWNED   0xFF	/* A return status for write mode command */

char		*WRwarning = "\nMake sure to press Control C on any other machines that\n   \
	want to write to the partitions released \n";

/*	Change History:
	1.0a    3/9/84 - put warning in on write release 
	1.0	02/20/84  Cleaned up user and internal interface
	0.0c	02/01/84  Changed ack check from 0x4D to 0x00
			  Made write release work on CPM/86
	0.0b	01/31/84  Cosmetic modifications
	0.0a	01/24/84  Utility written
*/



main( argc, argv)		/* main line of program */
	int argc;
	CHAR *argv[];
	{
	printf( "Release Utility -- version %d.%d%c%c\n",ver,rev,mod,asm);
	listUpper( argc, argv);
	if (argc > 1) 
		{
		dorelease( argc, argv);
		}
	else 	{
		helpmsg();
		}
#ifdef cpm80
	return 0;
#endif
	}


helpmsg()			/* information, please */
{
printf("\nPurpose: to terminate spool job, release locks, or rescind write ownership");
printf("\n\nFormat:\n");
printf("   RELEASE SPOOL or\n");
printf("   RELEASE LOCKS or\n");
printf("   RELEASE BOTH  (to release spool and locks) or\n");
printf("   RELEASE W <drive letter> ... (to release write ownership on given drives) or\n");
printf("   RELEASE W     (to release write ownership on all drives) or\n");
printf("   RELEASE ALL   (to do all of the above on all drives)\n");
}

/*page*/

dorelease( argc, argv)
	int argc;
	CHAR *argv[];
	{
	switch( *argv[1] )
		{
		case 'S':	/* release spool */
			relspool();
			break;
		case 'B':	/* release both spool and locks like in */
				/* CPM warm boots */
			relspool();
		case 'L':	/* release locks */
			rellocks();
			break;
		case 'A':	/* release all */
			relspool();
			rellocks();
		case 'W':
			if (argc < 3)
				relAllDrives();
			else
				relListedDrives( argc, argv);
			break;
		default:
			helpmsg();
			break;
		}
	}



relspool()
	{
	/* will happen automatically on warm boot in CP/M 2.2 and CP/M-86 */
#ifdef msdos
	bios86( 1, 14);		/* bios function 14 releases spool job */
#endif
	}



rellocks()
	{
	/* will happen automatically on warm boot in CP/M 2.2 and CP/M-86 */
#ifdef msdos
	bios86( 1, 16);		/* bios function 16 releases all locks*/
#endif
	}

/*page*/

relAllDrives()			/* Release write protection on all drives */
	{
	int curdrive = 0;
	struct GetInfoStruct getbuffer;
	struct WMstruct x;

	while (GetAssign( curdrive, &getbuffer) == 0) 
		{
		if (getbuffer.GetUnit != UNASSIGNED &&
		    getbits( getbuffer.GetCtl, 5, 2) == 2) 
			{
			/* set up parameters for bios write query call */
			x.wmsend.WMcmd = WMquery;
			x.wmsend.WMvol = getbuffer.GetVol;
			x.wmsend.WMunit = getbuffer.GetUnit;
			x.wmsend.WMuserno = userno();
			x.wmsend.WMvalue = userno();
			x.logdrive = curdrive;

			writemode( &x );	/* query drive ownership */

			if (x.wmrec.WMstatus == userno()) 
				{
				reldrive( curdrive );
				}
			}
		curdrive++;
		}	/* end of while */
	printf ("%s%c",WRwarning,7);
	}


relListedDrives( argc, argv)	/* Release write protection on listed drives */
	int argc;
	CHAR *argv[];
	{
	argc -= 2;	/* adjust to get at drive letters */
	argv += 2;

	while (--argc >= 0) 
		{
		reldrive( *(*argv++) - 'A' );
		}
	printf ("%s%c",WRwarning,7);
	}

/*page*/

reldrive( curdrive )	/* release write protection on one drive */
	int curdrive;
	{
	int code;
	struct GetInfoStruct getbuffer;
	struct WMstruct wmparm;

	if ((code = GetAssign( curdrive, &getbuffer)) != 0) 
		{
		printf("Drive %c: GetAssign error code %02x\n",
			curdrive + 'A', code);
		}
	else 	{
		/* set up parameters for write release bios call */
		wmparm.wmsend.wmcmd = WMCMD;	/* set up request */
		wmparm.wmsend.WMcmd = WMrelease;
		wmparm.wmsend.WMvol = getbuffer.GetVol;
		wmparm.wmsend.WMunit = getbuffer.GetUnit;
		wmparm.wmsend.WMvalue = userno();
		wmparm.wmsend.WMuserno = userno();

		wmparm.logdrive = curdrive;
#ifdef dbg
		printf("releasing ");
		printf("drive %c, vol %d, unit %d, value %d, user %d\n",
			wmparm.logdrive + 'A',
			wmparm.wmsend.WMvol,
			wmparm.wmsend.WMunit,
			wmparm.wmsend.WMvalue,
			wmparm.wmsend.WMuserno);
#endif
		writemode( &wmparm );		/* make request */
#ifdef dbg
		printf("response: ack %02x, status %02x\n",
			wmparm.wmrec.WMack,
			wmparm.wmrec.WMstatus);
#endif
						/* interpret response */
		if (wmparm.wmrec.WMack != MESACK ||
		    wmparm.wmrec.WMstatus != NOT_OWNED)
			printf("Drive %c: write ownership release error\n",
				curdrive + 'A');
		else
			printf("Drive %c: write ownership released\n",
				curdrive + 'A');
		}
	}
