
/*
 *  EXPAND.C
 *
 */

#include "defs.h"

#include <exec/memory.h>

extern void *AllocMem();
extern struct FileLock *Lock();
extern struct FileLock *CurrentDir();

#ifndef NULL
#define NULL 0L
#endif

struct DPTR {			 /* Format of directory fetch pointer */
   struct FileLock *lock;	 /* lock on directory	*/
   struct FileInfoBlock *fib;	 /* mod'd fib for entry */
};

struct DPTR *
dopen(name, stat)
char *name;
register int *stat;
{
    register struct DPTR *dp;

    *stat = 0;
    dp = (struct DPTR *)malloc(sizeof(struct DPTR));
    /*
    *if (*name == '\0')
    *	 dp->lock = DupLock (Clock);
    *else
    */
    dp->lock = Lock (name, ACCESS_READ);
    if (dp->lock == NULL) {
	free (dp);
	return (NULL);
    }
    dp->fib = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC);
    if (!Examine (dp->lock, dp->fib)) {
	perror (name);
	dclose (dp);
	return (NULL);
    }
    if (dp->fib->fib_DirEntryType >= 0)
	*stat = 1;
    return (dp);
}

dnext(dp, pname, stat)
register struct DPTR *dp;
char **pname;
int *stat;
{
    if (dp == NULL)
	return (0);
    if (ExNext (dp->lock, dp->fib)) {
	*stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
	*pname = dp->fib->fib_FileName;
	return (1);
    }
    return (0);
}


dclose(dp)
register struct DPTR *dp;
{
    if (dp == NULL)
	return (1);
    if (dp->fib)
	FreeMem (dp->fib, sizeof(*dp->fib));
    if (dp->lock)
	UnLock (dp->lock);
    free (dp);
    return (1);
}


isdir(file)
char *file;
{
    register struct DPTR *dp;
    int stat;

    stat = 0;
    if (dp = dopen (file, &stat))
	dclose(dp);
    return (stat == 1);
}


free_expand(av)
register char **av;
{
    register char **base = av;

    if (av) {
	while (*av) {
	    free (*av);
	    ++av;
	}
	free (base);
    }
}

/*
 * EXPAND(wild_name, pac)
 *    wild_name      - char * (example: "df0:*.c")
 *    pac	     - int  *  will be set to # of arguments.
 */


char **
expand(base, pac)
char *base;
int *pac;
{
    register char *ptr;
    char **eav = (char **)malloc (sizeof(char *));
    short eleft, eac;
    char *name;
    char *bname, *ename, *tail;
    int stat, scr;
    register struct DPTR *dp;

    *pac = eleft = eac = 0;

    base = strcpy(malloc(strlen(base)+1), base);
    for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
    for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
    if (ptr < base) {
	bname = strcpy (malloc(1), "");
    } else {
	scr = ptr[1];
	ptr[1] = '\0';
	bname = strcpy (malloc(strlen(base)+1), base);
	ptr[1] = scr;
    }
    ename = ptr + 1;
    for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
    scr = *ptr;
    *ptr = '\0';
    tail = (scr) ? ptr + 1 : (char *)NULL;

    if ((dp = dopen (bname, &stat)) == NULL  ||  stat == 0) {
	free (bname);
	free (base);
	free (eav);
	puts ("Could not open directory");
	return (NULL);
    }
    while (dnext (dp, &name, &stat)) {
	if (WildCmp(ename, name)) {
	    if (tail) {
		int alt_ac;
		char *search, **alt_av, **scrav;
		struct FileLock *lock;

		if (!stat)           /* expect more dirs, but this not a dir */
		    continue;
		lock = CurrentDir (dp->lock);
		search = malloc(strlen(name)+strlen(tail)+2);
		strcpy (search, name);
		strcat (search, "/");
		strcat (search, tail);
		scrav = alt_av = expand (search, &alt_ac);
		CurrentDir (lock);
		if (scrav) {
		    while (*scrav) {
			if (eleft < 2) {
			    char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
			    movmem(eav, scrav, (eac + 1) << 2);
			    free (eav);
			    eav = scrav;
			    eleft = 10;
			}
			eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
			strcpy(eav[eac], bname);
			strcat(eav[eac], *scrav);
			free (*scrav);
			++scrav;
			--eleft, ++eac;
		    }
		    free (alt_av);
		}
	    } else {
		if (eleft < 2) {
		    char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
		    movmem(eav, scrav, (eac + 1) << 2);
		    free (eav);
		    eav = scrav;
		    eleft = 10;
		}
		eav[eac] = malloc (strlen(bname)+strlen(name)+1);
		eav[eac] = strcpy(eav[eac], bname);
		strcat(eav[eac], name);
		--eleft, ++eac;
	    }
	}
    }
    dclose (dp);
    *pac = eac;
    eav[eac] = NULL;
    free (bname);
    free (base);
    if (eac)
	return (eav);
    free (eav);
    return (NULL);
}

/*
 *  OUTDATED()
 *
 *  if date(dest) < date(src) return true
 */

OutDated(dest, src, validright)
char *dest, *src;
short *validright;
{
    struct FileLock *lock, *lock2;
    FIB *fib = malloc(sizeof(FIB));
    DATESTAMP Ds;
    short result = 1;

    if (lock = Lock(dest, SHARED_LOCK)) {
	if (Examine(lock, fib) && fib->fib_DirEntryType < 0) {
	    Ds = fib->fib_Date;
	    if (lock2 = Lock(src, SHARED_LOCK)) {
		if (Examine(lock2, fib) && fib->fib_DirEntryType < 0) {
		    if (Ds.ds_Days > fib->fib_Date.ds_Days)
			result = 0;
		    else if (Ds.ds_Days == fib->fib_Date.ds_Days) {
			if (Ds.ds_Minute > fib->fib_Date.ds_Minute)
			    result = 0;
			else if (Ds.ds_Minute == fib->fib_Date.ds_Minute) {
			    if (Ds.ds_Tick > fib->fib_Date.ds_Tick)
				result = 0;
			}
		    }
		}
		UnLock(lock2);
	    }
	}
	UnLock(lock);
    }
    if (result == 0) {
	*validright = 1;
    } else {
	*validright = 0;
	if (lock = Lock(src, SHARED_LOCK)) {
	    if (Examine(lock, fib) && fib->fib_DirEntryType < 0)
		*validright = 1;
	    UnLock(lock);
	}
    }
    free(fib);
    return(result);
}

