/*
 * paths.c  V2.1

 * DOS Paths handling routines
 *
 * (c) 1991-96 Stefan Becker
 *
 */

/* Handler includes */
#include "wbstart.h"

/* Local data structures */
struct PathListEntry {
 BPTR ple_Next; /* Next PathListEntry */
 BPTR ple_Lock; /* Directory lock     */
};

/* Local data */
static struct PathListEntry *LoadPath;       /* Path for loading programs    */
static struct PathListEntry *WorkbenchPath;  /* Copy of Workbench path       */
static struct PathListEntry *OldProcessPath; /* Pointer to process' old path */

/* Scan load path for program and return directory lock */
BPTR ScanLoadPath(char *name, BPTR currentdir)
{
 BPTR rc;

 /* Check current directory first */
 if (rc = Lock(name, ACCESS_READ)) {

  DEBUGLOG(kprintf("Program found in current directory\n");)

  /* Program found, unlock it */
  UnLock(rc);

  /* Return current directory as home directory */
  rc = currentdir;

 } else {
  struct PathListEntry *current = LoadPath;

  /* Program not found, scan path list */
  while (current) {
   BPTR filelock;

   DEBUGLOG(kprintf("Scanning load path 0x%08lx\n", current->ple_Lock);)

   /* Go to directory */
   CurrentDir(current->ple_Lock);

   /* Program in this directory? */
   if (filelock = Lock(name, ACCESS_READ)) {

    /* Yes, unlock it */
    UnLock(filelock);

    /* Set return code */
    rc = current->ple_Lock;

    /* Leave loop */
    break;
   }

   /* Next entry */
   current = BADDR(current->ple_Next);
  }

  /* Go back to current directory */
  CurrentDir(currentdir);
 }

 /* Return home directory lock */
 return(rc);
}

/* Free a path list */
static void FreePathList(struct PathListEntry *list)
{
 struct PathListEntry *current;
 struct PathListEntry *next    = list;

 /* Scan list */
 while (current = next) {

  /* Save pointer to next entry */
  next = BADDR(current->ple_Next);

  /* Release lock */
  UnLock(current->ple_Lock);

  /* Free current path list entry */
  FreeMemory(current);
 }
}

/* Copy a path list */
static struct PathEntryList *CopyPathList(struct PathListEntry *orig)
{
 struct PathListEntry *head    = NULL; /* Head of copied path list          */
 struct PathListEntry *current = NULL; /* Current entry in copied path list */
 struct PathListEntry *next    = NULL; /* Next allocated path list entry    */

 /* Scan original path list */
 while (orig) {

  /* Allocate memory for path list entry */
  if ((next != NULL) ||
      (next = AllocateMemory(sizeof(struct PathListEntry)))) {

   /* Duplicate directory lock */
   if (next->ple_Lock = DupLock(orig->ple_Lock)) {

    /* Lock duplicated, clear pointer to next node */
    next->ple_Next = NULL;

    /* List empty? */
    if (head)

     /* No, append new entry after current entry */
     current->ple_Next = MKBADDR(next);

    else

     /* Yes, new entry is head of list, save pointer */
     head = next;

    /* Move current pointer */
    current = next;

    /* Clear next pointer. A new entry must be allocated in the next round. */
    next = NULL;
   }

   /* Couldn't allocate memory for path list entry */
  } else {

   /* Free path list */
   FreePathList(head);

   /* Clear pointer */
   head = NULL;

   /* Leave loop */
   break;
  }

  /* Get next entry in original path list */
  orig = BADDR(orig->ple_Next);
 }

 /* Next path list entry already allocated? Free it! */
 if (next) FreeMemory(next);

 /* Return pointer to head of copied path list */
 return(head);
}

/* Copy path from Workbench process and install it as our process' path */
void InstallWorkbenchPath(void)
{
 struct CommandLineInterface *cli = Cli();
 struct Process *wbproc;

 /* Get pointer to our old path */
 OldProcessPath = (struct PathList *) BADDR(cli->cli_CommandDir);

 /* Set this path as default load path */
 LoadPath = OldProcessPath;

 /* Clear pointer to Workbench path */
 WorkbenchPath = NULL;

 /* Find Workbench task and make sure it is a DOS process */
 if ((wbproc = (struct Process *) FindTask("Workbench")) &&
     (wbproc->pr_Task.tc_Node.ln_Type == NT_PROCESS)) {
  struct CommandLineInterface *wbcli;

  /* Make sure it is a CLI process and copy the path */
  if ((wbcli = BADDR(wbproc->pr_CLI)) &&
      (WorkbenchPath = CopyPathList((struct PathList *)
                                    BADDR(wbcli->cli_CommandDir)))) {

   DEBUGLOG(kprintf("Workbench path copied and installed.\n");)

   /* Path successfully copied, install it in our process */
   cli->cli_CommandDir = MKBADDR(WorkbenchPath);

   /* Use workbench path as load path */
   LoadPath = WorkbenchPath;
  }
 }
}

/* Remove Workbench path */
void RemoveWorkbenchPath(void)
{
 /* Copy of Workbench path valid? */
 if (WorkbenchPath) {

  /* Yes, reinstall our old path */
  Cli()->cli_CommandDir = MKBADDR(OldProcessPath);

  /* Free Workbench Path */
  FreePathList(WorkbenchPath);
 }
}
