/*
 *  $RCSfile: files.c,v $ 
 *  $Release$
 *  $Revision: 1.2 $
 *  $Date: 92/12/13 23:54:19 $
 *  $Author: tf $
 *  $State: Exp $
 */

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

extern struct DosLibrary *DosBase;

struct FileLock *Lock(), *DupLock(), *CurrentDir(), *ParentDir();

unsigned long coptions=0L; /* is only accessed by: */

#define SETOPT(o) coptions |= (o)
#define CLROPT(o) coptions &=~(o)

#define OPT_RECURSIVE (1L<<0)  /* enter sub-directories */
#define OPT_NOICONS   (1L<<1)  /* skip .info files */
#define OPT_QUOTE     (1L<<2)  /* skip .info files */

#define RECURSIVE ((coptions & OPT_RECURSIVE) !=NULL)
#define NOICONS   ((coptions & OPT_NOICONS)   !=NULL)
#define QUOTE     ((coptions & OPT_QUOTE)     !=NULL)

static char rcs_id[]= "$VER: $Id: files.c,v 1.2 92/12/13 23:54:19 tf Exp $";

#define BANNER &rcs_id[6]

void buythefarm(void)
{ exit(0);
}

void _abort(void)
{ puts("^C\n\n***BREAK");
  buythefarm();
}

static char *whoami,      /* copy of argv[0] (for perror) */
            *prefix="",   /* output line prefix */
            *postfix="";  /* output line postfix */

#include <stdarg.h>

void perror(const char *fmt, ...)
{
  va_list argp;
  va_start(argp,fmt);
  fprintf(stderr,"\r%s: ",whoami);
  vfprintf(stderr,fmt,argp);
  fprintf(stderr,"\n");
  fflush(stderr);
  va_end(argp);
}

/*
 * getcdn() exreacts the current directory name from the CLI structure and
 * copies it into the buffer.
 */

int getcdn(char *buf, int len)
{ struct Process *proc= (struct Process *)FindTask(NULL);
  BYTE l=0;
  if(proc)
  { char *cdn= (char *)
      BADDR(((struct CommandLineInterface *)BADDR(proc->pr_CLI))->cli_SetName);
    l=((*cdn<len)?*cdn:len);
    while(l--) *buf++ = *++cdn;
    *buf='\0';
  }
  return(l);
}

/*
 * Get full pathname out of the given path
 */

char *getfpn(char *path)
{
  static char fpn[256];
  struct FileLock *lock;
  struct FileInfoBlock *fib= (struct FileInfoBlock *)
    AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC);
  char *s= &fpn[255];
  *s= '\0';
  if(fib)
  { if(lock= Lock(path, SHARED_LOCK))
    { while(lock)
      { if(Examine(lock,fib))
        { char *t= fib->fib_FileName;
          int l=0;
          *--s= (lock=ParentDir(lock))?'/':':';
          while(*t)
          { t++;
            l++;
          }
          while(l--) *--s= *--t;
        }
      }
      UnLock(lock);
    }
    else perror("Can't find %s\nError code %ld.",path,IoErr());
    FreeMem(fib,sizeof(struct FileInfoBlock));
  }
  else perror("Error: Ran out of memory");
  return(s);
}

void perform(char *path)
{
  char fstr[512];
  struct FileLock *lock;
  if(lock= Lock(path,SHARED_LOCK))
  { struct FileInfoBlock *fib= (struct FileInfoBlock *)
       AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC);
    if(fib)
    { if(Examine(lock,fib)!=DOSFALSE)
      { if(QUOTE) sprintf(fstr,"%s\"%s%%s\"%s\n",prefix,getfpn(path),postfix);
        else sprintf(fstr,"%s%s%%s%s\n",prefix,getfpn(path),postfix);
        while(ExNext(lock,fib)!=DOSFALSE)
        { if(fib->fib_DirEntryType < 0)
            printf(fstr,fib->fib_FileName);
          else if(RECURSIVE)
          { char temp[256];
            sprintf(temp,"%s%s",getfpn(path),fib->fib_FileName);
            perform(temp);
          }
        }
      }
      FreeMem(fib,sizeof(struct FileInfoBlock));
    }
    else perror("Error: Ran out of memory");
    UnLock(lock);
  }
  else perror("Can't find %s\nError code %ld.",path,IoErr());
}

void perform17(char *path)
{ char cdn[256];
  struct FileLock *lock, *old;
  if(lock= Lock(path, SHARED_LOCK))
  { old= CurrentDir(lock);
    getcdn(cdn,256);
    puts(cdn);
    /*lfiles(lock);*/
    CurrentDir(old);
    UnLock(lock);
  }
  else perror("Error code %ld.\n",IoErr());
}


void main(int argc, char *argv[])
{
  char *path= "";
  onbreak(_abort);     /* this is DICE */
  whoami= argv[0];     /* and this is me */
  BOOL badopt= FALSE;  /* bad option? */

  if(argc>1)
  { --argc;
    ++argv;
    while(argc>0 && !badopt)
    { char *arg=argv[0];
      if(*arg=='-')
      { arg++;
        switch(*arg)
        { case 'r': case 'R': /* enter sub-dirs */
            SETOPT(OPT_RECURSIVE);
            break;
          case 'i': case 'I': /* skip .info files */
            SETOPT(OPT_NOICONS);
            break;
          case 'q': case 'Q': /* quote filename */
            SETOPT(OPT_QUOTE);
            break;
          case 'p': /* prefix */
            if(arg[1]) prefix= &arg[1];
            else { ++argv;
                   --argc;
                   prefix= argv[0];
                 }
            break;
          case 'P': /* postfix */
            if(arg[1]) postfix= &arg[1];
            else { ++argv;
                   --argc;
                   postfix= argv[0];
                 }
            break;
          default:
            perror("Bad option: -%c.",*arg);
            badopt=TRUE;
            break;
        }
      }
      else if(*arg=='?'||*arg=='.')
      { badopt= TRUE;
        break;
      }
      else path=arg;
      --argc;
      ++argv;
    }
  }
  if(!badopt)
    perform(path);
  else
  { puts(BANNER);
    puts("(c)Copyright 1990-92 by Tobias Ferber, All Rights Reserved");
    puts("FILES [pathname] [-p prestr] [-P poststr] [-r] [-q]");
  }
  buythefarm();
}
