(c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
The information contained herein is subject to change without notice, and 
is provided "as is" without warranty of any kind, either expressed or implied.  
The entire risk as to the use of this information is assumed by the user.



                    WHICH.C - Locates your commands

     Which.c is a command that helps you to find your other commands.  It 
searches your current directory, then your paths, then C: just as AmigaDOS
does when trying to load a CLI command.  It is extremely useful when you 
want to update a command on your hard drive but have forgotten where you 
put it.  It can also tell you the name of a directory assigned to a logical 
label (example:  which devs:).  In addition, which.c provides example source 
for path searching and building of full path names.


/*
 *  which.c  ---  C. Scheppner  CBM  1/87
 *
 *     Usage:  which filename
 *     Tells you the path to named command or directory
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>

#define SBUFSZ 256
#define CBUFSZ 80

extern BOOL getPath();

struct Path
   {
   BPTR  path_Next;
   LONG  path_Lock;
   };

main(argc,argv)
int argc;
char **argv;
   {
   struct Process *proc;
   struct CommandLineInterface *cli;
   struct Path *path;
   struct FileInfoBlock *fib;
   APTR oldWindowPtr;
   LONG lock, startcd;
   BOOL Found, InitialCD, FullPath;
   int  i;
   char *command, sbuf[SBUFSZ], cbuf[CBUFSZ];

   /* Fail from WB, give usage from CLI if command name not passed */
   if(argc == 0)  exit(RETURN_ERROR);
   if((argc != 2)||(*argv[1]=='?'))
      printf("Usage: which filename\n"), exit(RETURN_OK);
   command = argv[1];

   /* Fail if not CLI process */
   proc = (struct Process *)FindTask(NULL);
   cli = (struct CommandLineInterface *)(proc->pr_CLI << 2);
   if(!cli)  exit(RETURN_ERROR);

   /* Allocate a FileInfoBlock - must be longword aligned */
   if(!(fib=(struct FileInfoBlock *)
     AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)))
      printf("Not enough memory\n"), exit(RETURN_FAIL);

   /* Save old WindowPtr, and disable volume requesters */
   oldWindowPtr = proc->pr_WindowPtr;
   proc->pr_WindowPtr = (APTR)-1L;

   /* Were we given full path in command name ? */
   for(FullPath = FALSE, i=0; i<strlen(command); i++)
     {
     if(command[i] == ':')
        {
        FullPath = TRUE;
        break;
        }
     }

   /* Check current directory */
   if(Found = getPath(command,fib,sbuf))
      {
      if((!FullPath)&&(command[0]))  strcpy(sbuf,command);
      }

   /* Check paths */
   if((!Found)&&(!FullPath))
      {
      InitialCD = TRUE;
      /* Follow the BPTR path list */
      for(path = (struct Path *) BADDR(cli->cli_CommandDir);
          (path) && (!Found);
            path = (struct Path *) BADDR(path->path_Next))
         {
         /* CD to each path */
         lock = CurrentDir(path->path_Lock);
         if(InitialCD)  startcd = lock, InitialCD = FALSE;

         /* See if command is there */
         Found = getPath(command,fib,sbuf);
         }
      /* If we CD'd anywhere, restore initial CD */
      if(! InitialCD)  CurrentDir(startcd);
      }

   /* Check C: */
   if((!Found)&&(!FullPath))
      {
      strcpy(cbuf,"C:");
      strcpy(&cbuf[2],command);
      if(Found = getPath(cbuf,fib,sbuf))  strcpy(sbuf,cbuf);
      }

   if(Found)  printf("%s\n",sbuf);
   else  printf("%s Not Found\n",command);

   /* Re-enable volume requesters */
   proc->pr_WindowPtr = oldWindowPtr;
   /* We wouldn't have got here if we hadn't allocated this */
   FreeMem(fib, sizeof(struct FileInfoBlock));

   /* Return warning if not found */
   exit(Found ? RETURN_OK : RETURN_WARN);
   }


BOOL
getPath(command,fib,buf)
char *command;
struct FileInfoBlock *fib;
char *buf;
   {
   LONG lock;
   BOOL Success = FALSE;

   if(lock = Lock(command,ACCESS_READ))
      {
      if(Examine(lock,fib))
         {
         /* File or Dir found.  To distinguish, check fib_DirEntryType */
         Success = TRUE;
         buildPath(lock,fib,buf);
         }
      UnLock(lock);
      }
   return(Success);
   }


buildPath(inlock,fib,buf)
LONG inlock;
struct FileInfoBlock *fib;
char *buf;
   {
   int i;
   LONG lock,oldlock;
   BOOL MyOldLock = FALSE;

   buf[0] = NULL;
   lock = inlock;

   while(lock)
      {
      if(Examine(lock,fib))
         {
         if(fib->fib_FileName[0] > ' ')
            {
            if(buf[0]) insert(buf,"/");
            insert(buf,fib->fib_FileName);
            }
         }
      oldlock = lock;
      lock = ParentDir(lock);
      if(MyOldLock)  UnLock(oldlock);
      else           MyOldLock = TRUE;
      }

   if(fib->fib_FileName[0] > ' ')
      {
      for(i=0; i<(strlen(buf)); i++)
         {
         if(buf[i] == '/')
            {
            buf[i] = ':';
            break;
            }
         }
      }
   else  insert(buf,"RAM:");

   return(strlen(buf));
   }

insert(buf,s)
char *buf,*s;
   {
   char tmp[SBUFSZ];

   strcpy(tmp,buf);
   strcpy(buf,s);
   strcpy(&buf[strlen(s)],tmp);
   }

strlen(s)
char *s;
   {
   int i = 0;
   while(*s++) i++;
   return(i);
   }


strcpy(to,from)
char *to, *from;
   {
   do
      {
      *to++ = *from;
      }
   while(*from++);
   }


