/*
 * The author of this software is Eric Grosse.  Copyright (c) 1993 by AT&T.
 * Permission to use, copy, modify, and distribute this software for any
 * purpose without fee is hereby granted, provided that this entire notice
 * is included in all copies of any software which is or includes a copy
 * or modification of this software and in all copies of the supporting
 * documentation for such software.
 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
 */

/* deprecated version of lsr.c, suitable for some non-POSIX systems */

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/dir.h>

#ifndef S_ISREG
#define S_ISREG(m) ((m)&S_IFREG)
#define S_ISDIR(m) ((m)&S_IFDIR)
#endif

#ifdef NOSYMLINK
#define lstat(f,s) stat(f,s)
#endif

typedef unsigned char uchar;

uchar *path, **component;
int ncomp;
int prsymlink = 0;
int prunixtime = 0;

char *
Malloc(n)
	size_t n;
{
	char	*p;
	if (!(p = malloc((size_t)n))){
		fprintf(stderr,"unable to allocate %d bytes\n",n);
		exit(1);
	}
	return p;
}

char *
Realloc(ReallocP, ReallocN)
	char *ReallocP;
	int ReallocN;
{
	if(!(ReallocP = realloc(ReallocP, ReallocN))){
		fprintf(stderr,"unable to reallocate %d bytes\n",ReallocN);
		exit(1);
	}
	return(ReallocP);
}

char*
Strdup(s)
	char* s;
{
	int l;
	if (!s)
		return 0;
	l = strlen(s)+1;
	return strcpy((char *)Malloc((size_t)l), s);
}

int
cmp(a,b)
	char *a, *b;
{
	return strcmp(*(char**)a,*(char**)b);
}

char **
sorted_names(dir)
	DIR *dir;
{
	int maxnames = 250;	/* starting guess at size of directory */
	int nnames = 0;
	char **names = (char **)Malloc(maxnames*sizeof(*names));
	char *file;
	struct direct *entry;

	while( entry = readdir(dir) ){
		file = entry->d_name;
		if(strcmp(file,".")!=0 && strcmp(file,"..")!=0 ){
			names[nnames++] = Strdup(file);
			if(nnames>=maxnames){
				maxnames += 200;
				names = (char **)Realloc(names,maxnames*sizeof(char*));
			}
		}
	}
	qsort((void*)names,nnames,sizeof(*names),cmp);
	names[nnames] = 0;
	return(names);
}

void
free_names(names)
	char **names;
{
	char **name;
	for(name = names; *name; name++)
		free(*name);
	free(names);
}


void
pr()
{
	struct stat s;
	DIR *dir;
	char buf[BUFSIZ];
	int cc;
	char **names, **name;

	if(lstat((char*)path,&s)){
		fprintf(stderr,"%s: ",path);
		perror("can't stat");
		return;
	}
#ifndef NOSYMLINK
	if(S_ISLNK(s.st_mode)){
		if(prsymlink){
			printf("%s -> ",path);
			cc = readlink((char*)path,buf,BUFSIZ);
			if (cc >= 0) {
				buf[cc] = 0;
				printf("%s\n",buf);
			}else{
				perror("can't readlink\n");
				exit(1);
			}
		}
	}else
#endif
	     if(S_ISREG(s.st_mode)){
		uchar *p = path;
		if(p[0]=='.' && p[1]=='/')
			p += 2;	/* chop off leading ./ */
		if(prunixtime)
			printf("%s %lu %lu 0\n",p,(unsigned long)s.st_mtime,
				(unsigned long)s.st_size);
		else
			printf("%s\n",p);
	}else if(S_ISDIR(s.st_mode)){
		if(dir = opendir((char*)path)){
			cc = strlen((char*)component[ncomp-1]);
			component[ncomp] = cc+component[ncomp-1]+1;
			component[ncomp][-1] = '/';
			ncomp++;
			names = sorted_names(dir);
			for(name = names; *name; name++){
				strcpy((char*)component[ncomp-1],*name);
				pr();
			}
			free_names(names);
			ncomp--;
			component[ncomp][-1] = '\0';
			closedir(dir);
		}else{
			fflush(stdout);
			fprintf(stderr,"can't opendir %s\n",(char*)path);
		}
	}else{
		fprintf(stderr,"%s mode %o\n",(char*)path,s.st_mode);
	}
}

int
main(argc,argv)
	int argc;
	char **argv;
{
	if(argc>1 && !strcmp(argv[1],"-s") ){
		prsymlink = 1;
		prunixtime = 0;
		argc--; argv++;
	}
	if(argc>1 && !strcmp(argv[1],"-t") ){
		prunixtime = 1;
		prsymlink = 0;
		argc--; argv++;
	}
	component = (uchar**)Malloc(1000*sizeof(uchar*));
		/* should check against depth */
	path = (uchar *)Malloc(4096);
		/* should be _POSIX_PATH_MAX */
	component[0] = path;
	ncomp = 1;
	if(argc>1){
		while(--argc){
			strcpy((char*)path,*++argv);
			pr();
		}
	}else{
		strcpy((char*)path,".");
		pr();
	}	
}