/*  connect.c - perform network connections/disconnections
 *
 *  Modifications:
 *
 *	31-Jul-1986 mz	Use tools.h definitions
 *	03-Mar-1987 bw	Stub DOS5 version
 *	30-Oct-1987 bw	Change 'DOS5' to 'OS2'
 */

#include "..\h\tools.h"
#include <string.h>

#include <dos.h>

/*  Forward internal declarations
 */
static int FindFreeDrive (void);
static int MachineConnect (char *con);

/*  FindFreeDrive - find the lowest drive that is not in use
 *
 *  returns 0-based index of first drive not in use
 */
static int FindFreeDrive ()
{
    union REGS regs;

    for (regs.x.bx = 1; regs.x.bx <= 26; regs.x.bx++) {
	regs.x.ax = 0x4409;
	intdos (&regs, &regs);
	if (regs.x.cflag)
	    return regs.x.bx-1;
	}
    return -1;
}

/*  MachineConnect - attempt a connection to a particular drive
 *
 *  MachineConnect will attempt a drive connection to a connection without
 *  a password, reusing a drive if it exists.
 *
 *  con 	text of connection
 *
 *  returns	drive token if successful, -1 otherwise
 */
static int MachineConnect (char *con)
{
    char dev[MAXPATHLEN];
    char path[MAXPATHLEN];
    union REGS regs;
    struct SREGS sregs;
    int i;

    segread (&sregs);
    sregs.es = sregs.ds;

    /* try existing connections first */
    for (i = 0; ; i++) {
	regs.x.ax = 0x5F02;
	regs.x.bx = i;
	regs.x.si = (unsigned) dev;
	regs.x.di = (unsigned) path;

	intdosx (&regs, &regs, &sregs);
	if (regs.x.cflag)
	    break;
	if (!strcmpi (con, path))
	    return ((int) (dev[0] | 0x20) - (int) 'a') | REALDRIVE;
	}

    /* try creating a new drive */
    if ((i = FindFreeDrive ()) == -1)
	return -1;
    dev[0] = (char) (i + 'a');
    dev[1] = ':';
    dev[2] = 0;
    con[strlen(con)+1] = 0;

    regs.x.ax = 0x5F03;
    regs.x.bx = 0x0004;
    regs.x.cx = 0x4D5A;
#if ( defined(M_I86CM) || defined (M_I86LM) || defined (M_I86HM) )
    segread( &sregs);
    sregs.ds = FP_SEG(dev);
    regs.x.si = FP_OFF(dev);
	 sregs.es = FP_SEG(con);
	 regs.x.di = FP_OFF(con);
    intdosx(&regs, &regs, &sregs);
#else
    regs.x.si = (unsigned) dev;
    regs.x.di = (unsigned) con;
    intdos (&regs, &regs);
#endif

    if (regs.x.cflag)
	return -1;
    else
	return i;
}

/*  Connect - take an arbitrary pathname and connect to the appropriate
 *  server.
 *
 *  connect takes a name in the form \\mach\path and attempts to connect to
 *  the named machine.	Since DOS 3.x has problems with connections, we
 *  attach the connection to a drive.
 *
 *  path	network name of the form
 *		    \\machine\path  -or-
 *		    \\machine\shortname\path
 *  con 	buffer to place the successful connection
 *  sub 	buffer to place the remainder of the path
 *
 *  returns	-1 if connection was not successful, otherwise
 *		returns drive token
 */
int Connect (path, con, sub)
char *path;
char *con;
char *sub;
{
    int drive;
    char *p;

    /* make sure double backslash present */
    if (!fPathChr (path[0]) || !fPathChr (path[1]))
	return -1;

    /* find end of machine name */
    p = path+2;
    while (*p && !fPathChr (*p))
	p++;

    Move ((char far *) path, (char far *) con, p-path);
    con[p-path] = 0;
    strcpy (sub, p);
    if ((drive = MachineConnect (con)) != -1)
	return drive;

    /* try finding end of shortname */
    p++;
    while (*p && !fPathChr (*p))
	p++;

    Move ((char far *) path, (char far *) con, p-path);
    con[p-path] = 0;
    strcpy (sub, p);
    if ((drive = MachineConnect (con)) != -1)
	return drive;

    return -1;
}

/*  fDisconnect - remove a network connection
 *
 *  fDisconnect will delete a connection to a particular drive
 *
 *  drive	drive token of drive to be torched
 *
 *  returns	TRUE iff disconnection was successful
 */
flagType fDisconnect (drive)
int drive;
{
    char bufDrive[3];
    union REGS regs;

    if (ISTMPDRIVE(drive)) {
	bufDrive[0] = (char) (TOKTODRV(drive) + 'A');
	bufDrive[1] = ':';
	bufDrive[2] = 0;

	regs.x.ax = 0x5F04;
	regs.x.si = (unsigned) bufDrive;

	intdos (&regs, &regs);
	return (flagType) (regs.x.cflag == 0);
	}
    else
	return TRUE;
}
