/****************************************************************************
* 
* A S S I G N D E V . C
*
*   Duplicate a device in place--Allowing multiple names to a device.
*
*   Phillip Lindsay (c) 1987 Commodore-Amiga, Inc.
*   Unlimited use granted as long as copyright remains intact.
*
****************************************************************************/

                                                              /* V23.08.87 */
/* Some changes and a bug fix were made by Olaf Seibert, KosmoSoft */

#include <exec/types.h>
#include <exec/nodes.h>
/* #include <exec/lists.h> */
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>


#ifdef AZTEC_C
#include <functions.h>
#else
	*** WARNING: YOU SHOULD BEST BE USING AZTEC C TO COMPILE THIS CODE ***
#endif

extern  struct  DosLibrary      *DOSBase;


/*
 * external functions found in "misc.c"
 */
extern  BSTR    ctob();
extern  char    *allocstr(),
                *btoc(),
                *strupper();
extern  BOOL    ourdevnode();
extern  struct DeviceNode
                *finddosnode();
extern  VOID    freedev(),
                dupdev(),
                adddosnode(),
                trunc(),
                memfill(),
                memcpy();

/*
 * External functions found in "fprints.c"
 */
extern  int     fprints(),
                fputs();
                
/*
 * Exit message numbers
 */

#define ERROR_NOT_FOUND   0
#define ERROR_NOT_REMOVED 1
#define ERROR_REMOVED     2
#define ERROR_COPIED      3

static char TxtError[]  = "Error: ";

main(argc,argv)
int argc;
char **argv;
{
                struct  RootNode    *rnode;     /* root node pointer     */
                struct  DosInfo     *dinfo;     /* DOS info pointer      */
    register    struct  DeviceNode  *dnode;     /* device entry pointer  */
    register            BPTR        *dnodelink; /* last device pointer   */
                        char        *bname,     /* tmp. ptr to bstr      */
                                    name[32],   /* tmp. for device name  */
                                    *oldname,   /* existing device name  */
                                    *newname;   /* new device name       */
                        int         status;     /* error flag            */
	            struct  FileHandle  *stdout = Output();

    if (argc == 3) { /* duplicate given device  */
        newname = argv[1];
        trunc(strupper(newname),':');
        
        if ( dnode = finddosnode(newname) ) { /* OIS V09.08.87 */
			static char exists[] = " already exists";
            if (dnode->dn_Type == DLT_DEVICE) {
                fprints(stdout, "Warning: Device %s:%s; ", newname, exists);
            } else {
                fprints(stdout, "%sVolume or directory %s:%s\n",
                    TxtError, newname, exists);
                exit((int) RETURN_ERROR);
            }
        }
        
        oldname = argv[2];
        trunc(strupper(oldname),':');

    } else if (argc == 2) { /* Try and remove specified device */
        oldname = argv[1];
        trunc(strupper(oldname),':');
        newname = NULL;
    } else { /* Give them usage info */ 
		if (argc != 0) { /* Started from a CLI */ /* OIS V23.08.87 */
            static char old[] = " [old device]\n";
	        fprints(stdout, "Usage: %s [new device]%s", argv[0], old);
	        fprints(stdout, "       %s%s", argv[0], old);
		}
        exit((int) RETURN_ERROR);
    }        
    
   
    rnode   = (struct RootNode *)  DOSBase->dl_Root;        /* Find root node */
    dinfo   = (struct DosInfo  *)  BADDR(rnode->rn_Info);   /* Now dos info   */
	dnodelink =                    &dinfo->di_DevInfo;      /* Our first link */

/*
 * Here we search for the given device name and once found we will duplicate
 * the entire device data structure.  Then we add a new device node with
 * the supplied name to the device list. If no "newname" is specified the
 * given device is removed from the device list and free memory for the device
 * node and device name. (normally you only delete nodes you created...I do 
 * take precautions to NOT delete existing system devices...I add a key to
 * the end of the device name to flag the device node as being created by
 * ASSIGNDEV. 
 */
    
    Forbid();          /* Protect ourselves */
    
    while (dnode = (struct DeviceNode *) BADDR(*dnodelink)) {
        if ( dnode->dn_Type == DLT_DEVICE )  /* Are dealing with a device? */
        {
            bname = (char *) BADDR(dnode->dn_Name);
            memcpy(bname, name, (ULONG)( bname[0] + 1 ) );
            if ( !( strcmp( oldname, strupper(btoc(name)) ) ) ) {
                if ( newname ) {                     /* Duplicate it ? */
                    dupdev(dnode,newname);
                    status = ERROR_COPIED;
                } else if ( ourdevnode(dnode) ) {    /* OIS V15.08.87 */
                    *dnodelink = dnode->dn_Next;     /* No, remove it */
                    freedev(dnode);
                    status = ERROR_REMOVED;
                } else {
                    status = ERROR_NOT_REMOVED;
                }                                    /* OIS V09.08.87 */
                break;
            }   
        }
        dnodelink = &dnode->dn_Next;
    }
 
    Permit(); 

    switch (status) { /* OIS V09.08.87 */
    case ERROR_NOT_FOUND:
        fprints(stdout, "%sDevice %s: not found\n", TxtError, oldname);
        status = RETURN_ERROR;
        break;
    case ERROR_NOT_REMOVED:
        fprints(stdout, "%sCannot remove device %s:\n", TxtError, oldname); 
        status = RETURN_ERROR;
        break;
    case ERROR_REMOVED:
        fprints(stdout, "Removed %s:\n",oldname);
        status = RETURN_OK;
        break;
    case ERROR_COPIED:
        fprints(stdout, "Duplicated %s: -> %s:\n",oldname,newname);
        status = RETURN_OK;
    }

    exit(status);
     
}

/* eof */
