/* dcc last.c -o prg:last -proto */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <exec/types.h>

/*#define DEBUG*/

long n;
struct tnode {
    char name[50];
    long size;
    long days, mins, ticks;
/*    struct tnode *older, *newer; not good when mode==REVERSE*/
    struct tnode *succ, *prev;
};
struct tnode *root=0, *nn;
struct FileInfoBlock *fib;
struct TagItem *ti={    /* Sinn ??? */
    TAG_END
};
BPTR mylock=0;
BOOL cont;
long i;
struct Process *pr;
char *ver="$VER: LastV1.0byCarstenLechte";
UBYTE *dir="";
BOOL mode=0;
#define REVERSE 1


struct tnode *newnode(struct FileInfoBlock *fib) {
    struct tnode *tn;
    if(!(tn=malloc(sizeof(struct tnode)))) return(0);
#ifdef DEBUG
    printf("NewNode: %lx %s\n", tn, fib->fib_FileName);
#endif
    strncpy(tn->name, fib->fib_FileName, 50);
    if(fib->fib_DirEntryType>0) tn->size=-1;
    else tn->size=fib->fib_Size;
    tn->days=fib->fib_Date.ds_Days;
    tn->mins=fib->fib_Date.ds_Minute;
    tn->ticks=fib->fib_Date.ds_Tick;
    tn->succ=0;
    tn->prev=0;
    return(tn);
}


void addnode(struct tnode *tn, struct tnode *newn) {
    long diff=0;  /* <0: tn newer, >0: newn newer  */
    if(newn->days!=tn->days) diff=newn->days-tn->days;
    else if(newn->mins!=tn->mins) diff=newn->mins-tn->mins;
         else if(newn->ticks!=tn->ticks) diff=newn->ticks-tn->ticks;
#ifdef DEBUG
    printf("addnode: diff: %ld\n", diff);
    printf("tn: %s\n", tn->name);
    printf("newn: %s\n", newn->name);
#endif
    if(mode==REVERSE) diff=-diff;
    if(diff<0) {
        if(tn->succ) addnode(tn->succ, newn);
        else tn->succ=newn;
    } else {
        if(tn->prev) addnode(tn->prev, newn);
        else tn->prev=newn;
    }
}


void printn(struct tnode *tn) {
#ifdef DEBUG
    printf("printn: %ld, %s\n", n, tn->name);
#endif
    if(tn->prev) printn(tn->prev);
    if(n) {
        printf("%-30s",tn->name);
        if(tn->size>=0) printf(" %10ld\n", tn->size);
        else printf("      (dir)\n");
        n--;
    }
    if(tn->succ) printn(tn->succ);
}



int main(int argc,char **argv) {
    long i;
    pr=(struct Process *)FindTask(0);
    if(argc==1) n=1;
    else if(argc==3) {
        n=atol(argv[2]);
        dir=argv[1];
    } if(argc==2) {
        n=atol(argv[1]);
        for(i=0;i<strlen(argv[1]);i++)
            if(((argv[1][i]<'0')||(argv[1][i]>'9'))&&(argv[1][i]!='-')) {
                dir=argv[1];
                n=1;
                break;
            }
    }
    if(n<0) {
        n=-n;
        mode=REVERSE;
    }
    if(argv[1][0]=='?') {
        puts("Last V1.0 is (C) by Carsten Lechte, D-2000 Norderstedt, Germany");
        puts("USAGE: Last [<dir>] [[-]<n>]=number of newest entries to display");
        puts("[-]: rather display oldest n entries");
        exit(0);
    }
    if(!(fib=AllocDosObject(DOS_FIB, ti))) exit(20);
    if(!(mylock=Lock(dir, ACCESS_READ))) {
/*    if(!(mylock=DupLock(pr->pr_CurrentDir))) {*/
        FreeDosObject(DOS_FIB, ti);  /* oder "0" statt "ti" ? */
        exit(20);
    }
#ifdef DEBUG
    printf("mylock: %lx\n", mylock*4);
#endif
    cont=Examine(mylock, fib);
    if(!cont) goto ende;
    if(fib->fib_DirEntryType<0) {
        puts("Grmpf. This is not a directory.");
        goto ende;
    }
/*    if(!(root=newnode(fib))) goto ende;*/ /* always yields currrent dir */
    if(!(cont=ExNext(mylock, fib))) goto ende;
    if(!(root=newnode(fib))) goto ende;

    while(cont=ExNext(mylock, fib)) {
#ifdef DEBUG
        puts("ExNext...");
#endif
        if(!(nn=newnode(fib))) goto ende;
        addnode(root, nn);
    }
    if(IoErr()!=ERROR_NO_MORE_ENTRIES) puts("Error reading direcory.");

    printn(root);

    ende:;
    UnLock(mylock);
    FreeDosObject(DOS_FIB, ti);
    return(0);
}
