Article View: comp.os.msdos.programmer
Article #2109Re: ls.c
From: Darrell Kitchen
Date: Wed, 05 Sep 1990 18:39
Date: Wed, 05 Sep 1990 18:39
550 lines
21782 bytes
21782 bytes
I found a problem already with the following code and the "-C" command-line
option. Look this over and see what I've found.
In article <4049@disk.UUCP> mangor@disk.UUCP (Darrell Kitchen) writes:
============================= LS.C ===========================================
#include <stdio.h>
/* if your <stdio.h> doesn't have memory allocation functions then
#include <alloc.h> or #include <malloc.h>
*/
#include <errno.h>
#include <mem.h>
#include <dir.h>
#include <dos.h>
#include <stat.h> /* should be #include <sys\stat.h> */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define nil '\0'
#define ALL_F 0xFF
================================ Add this ==================================
#define ERR_F 0x1F
#define EOL(c) (((c)=='\n' || (c)==nil) ? TRUE : FALSE)
#define DY(date_) (((date_ & 0xFE00) >> 9) + 80)
#define DATE_DAY(date_) (date_ & 0x001F)
#define DATE_MON(date_) ((date_ & 0x01E0) >> 5)
#define DATE_YEAR(date_) (DY(date_) == 100 ? 0 : DY(date_))
#define T(t_) ((t_ & 0xF800) >> 11)
#define TH(time_) (T(time_) == 0 ? 12 : T(time_))
#define TIME_SEC(time_) (time_ & 0x001F)
#define TIME_MIN(time_) ((time_ & 0x07E0) >> 5)
#define TIME_HOUR(time_) (T(time_) > 12 ? TH(time_) = 12 : TH(time_))
#define AP(time_) ((T(time_) > 12 && TIME_MIN(time_) > 0) ? 'p' : 'a')
struct d_info {
struct ffblk *f_inf;
struct d_info *prev, *next;
};
#define crlf() printf("\n\r");
static char *months[12] = {
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
};
static struct d_info *head;
static struct stat f_stat;
static char Cf,Ff,Rf,af,bf,cf,df,ff,gf,If,lf,mf,nf,of,pf,qf,rf,sf,tf,uf,xf,zf;
/* ^ command line option flags */
static int F_FLAG=0; /* file search flag */
static int tfiles=0; /* total files found for request */
static char *path; /* file found at requested directory path */
static char *fpath; /* to hold the filepath for call to ff_stat() */
int nfexit(val,opt) int val, opt; {
printf("\nls: ");
switch(val) {
case 1: printf("illegal option == %c\n",opt);
printf("usage: ls =RadCxmnlogrtucpFbqisfz [files]\n");
}
exit(val);
}
int istok(ch,str) const char ch; char *str; {
int i;
for(i=0;;i++) {
if(str[i]==ch) return(i);
==============================[ CHANGE THIS ]============================
if(str[i]==nil) return(0); |
=========================================================================
==================================[ TO ]=================================
| if(!str[i]) return(ERR_F); |
=========================================================================
}
}
int is_exec(dir) struct d_info *dir; {
int i;
for(i=0;dir->f_inf->ff_name[i]!='.';i++)
if(dir->f_inf->ff_name[i]==nil) break;
if(!strncmp(&(dir->f_inf->ff_name[i]),".bat",4)) return(TRUE);
if(!strncmp(&(dir->f_inf->ff_name[i]),".exe",4)) return(TRUE);
if(!strncmp(&(dir->f_inf->ff_name[i]),".com",4)) return(TRUE);
if(!strncmp(&(dir->f_inf->ff_name[i]),".bin",4)) return(TRUE);
if(!strncmp(&(dir->f_inf->ff_name[i]),".obj",4)) return(TRUE);
if(!strncmp(&(dir->f_inf->ff_name[i]),".sys",4)) return(TRUE);
if(!strncmp(&(dir->f_inf->ff_name[i]),".lib",4)) return(TRUE);
return(FALSE);
}
int pr_time(dir) struct d_info *dir; {
printf("%02d:%02d ",
TH(dir->f_inf->ff_ftime),
TIME_MIN(dir->f_inf->ff_ftime));
return(0);
}
int ff_stat(dir,f_stat) struct d_info *dir; struct stat *f_stat; {
FILE *f1;
char *fname;
memset(f_stat,0,sizeof(struct stat));
if(dir->f_inf->ff_attrib & FA_DIREC) return(1); /* cant open directory */
if(dir->f_inf->ff_attrib & FA_LABEL) return(1); /* and label entries */
fname=(char *)calloc(1,215);
strcpy(fname,fpath);
strcat(fname,dir->f_inf->ff_name);
f1=fopen(fname,"r");
if(f1==NULL) {
printf("ls: error %d in ff_stat (%s)\n",errno,fname);
free(fname);
exit(0);
}
fstat(fileno(f1),f_stat);
fclose(f1);
free(fname);
return(0);
}
int pr_inode() {
printf("%5.1d ",f_stat.st_ino);
/* msdos doesnt provide i=node info; unix dependent */
return(0);
}
int pr_uid(dir) struct d_info *dir; {
if(nf && gf) return(0);
if(nf) printf("%4.1d ",f_stat.st_uid);
else if(of || lf) {
if(dir->f_inf->ff_attrib & FA_SYSTEM)
printf("sys "); else printf("dos ");
}
/* msdos doesnt provide user id info; unix dependent */
return(0);
}
int pr_gid(dir) struct d_info *dir; {
if(nf && of) return(0);
if(nf) printf("%4.1d ",f_stat.st_gid);
else if(gf || lf) {
if(dir->f_inf->ff_attrib & FA_SYSTEM)
printf("sys "); else printf("dos ");
}
/* msdos doesnt provide group id info; unix dependent */
return(0);
}
int pr_links() {
printf("%3.1d ",f_stat.st_nlink); /* always 1 in msdos */
return(0);
}
int pr_block(dir) struct d_info *dir; {
int block=0; /* in unix each dir entry has a size larger then 0 */
/* in pc/msdos each dir entry has a size of 0 */
/* but the dir entry occupies a 512 byte block */
/* although not alone = i.e. more then one entry in */
/* each block */
block=dir->f_inf->ff_fsize / 512;
if(block == 0) block = 1;
printf("%4.1d ",block);
return(0);
}
int pr_stat(dir) struct d_info *dir; { /* 0123456789 */
char attlist[11]; /* ========== */
/* drwxrwxhsl */
memset(attlist,'-',10);
attlist[10]=nil;
attlist[1]='r'; attlist[2]='w';
attlist[4]='r'; attlist[5]='w';
if(dir->f_inf->ff_attrib & FA_DIREC) attlist[0]='d';
if(dir->f_inf->ff_attrib & FA_RDONLY) {
attlist[2]='-'; attlist[5]='-';
}
if((dir->f_inf->ff_attrib & FA_DIREC) ||
(is_exec(dir)) || (f_stat.st_mode & S_IEXEC)) {
attlist[3]='x'; attlist[6]='x';
}
if(dir->f_inf->ff_attrib & FA_HIDDEN) {
attlist[7]='h'; /* hidden should be honored as not readable */
attlist[1]='-'; /* so in that aspect remove 'r' from 1,4 */
attlist[4]='-';
}
if(dir->f_inf->ff_attrib & FA_SYSTEM) attlist[8]='s';
if(dir->f_inf->ff_attrib & FA_LABEL) attlist[9]='l';
printf("%-11s",attlist);
return(0);
}
int pr_date(dir) struct d_info *dir; {
printf("%s %2.0d %2.0d ",
months[DATE_MON(dir->f_inf->ff_fdate) = 1],
DATE_DAY(dir->f_inf->ff_fdate),
DATE_YEAR(dir->f_inf->ff_fdate));
return(0);
}
int pr_size(dir) struct d_info *dir; {
printf("%7.1ld ",dir->f_inf->ff_fsize);
return(0);
}
int pr_name(dir) struct d_info *dir; {
struct stat f_stat;
============================[ add this ]================================
| char *str; |
| int i; |
| |
| str=(char *)calloc(1,128); |
| strcpy(str,dir= f_inf->ff_name); |
========================================================================
ff_stat(dir,&f_stat);
==========================[ CHANGE THIS ]================================
printf("%s",dir->f_inf->ff_name); |
if((Ff || pf) && (dir->f_inf->ff_attrib & FA_DIREC)) printf("\\");|
if(Ff && (is_exec(dir))) printf("*"); |
=========================================================================
===============================[ TO ]===================================
| i=strlen(str)+1; |
| if((Ff || pf) && (dir= f_inf->ff_attrib & FA_DIREC)) |
| str[strlen(str)]='\\'; |
| if(Ff && (is_exec(dir))) str[strlen(str)]='*'; |
| if(Cf && (mod % 5 != 4)) for(i=strlen(str);i<=14;i++) str[i]=' ';|
| str[i]=nil; |
| printf("%s",str); |
| free(str); |
========================================================================
If flag(Cf) is on then the string to be displayed needs to be extended
out as if a call to gotoxy(mod * 15,wherey()) were called. Since I was
having problems with that call, and since it would make portability to
MSC or QC a bit nasty, i just decided to add white spaces to extend it
15 = strlen(str), and only when the modulo value is 4.
The line: i=strlen(str)+1; and str[i]=nil; will work under any condition
provided that the entire length of "str" is longer then strlen(str)+1. If
it weren't then you would be trashing up the data segment. That is why I
calloc()'d it to 128 = to be on the safe side.
Also the directory indicator ('\') and the executable indicator ('*') were
imbedded in "str" this time instead of using seperate printf() statements.
return(0);
}
===========================[ DELETE THESE ]=============================
int fa_arch(dir) struct d_info *dir; { |
char attrib; |
|
attrib=dir->f_inf->ff_attrib; |
attrib &= FA_ARCH; |
if(attrib == FA_ARCH) return(TRUE); |
return(FALSE); |
} |
|
int fa_norm(dir) struct d_info *dir; { |
if(dir->f_inf->ff_attrib & FA_LABEL) return(TRUE); |
if(dir->f_inf->ff_attrib & FA_DIREC) return(TRUE); |
return(FALSE); |
} |
|
========================================================================
The above functions just take up space. They arent called by any other
function, and unless you specifically want to keep them, then just delete
them.
struct d_info *getdirstruct() { /* create memory space for struct */
struct d_info *head, *next, *dir;
struct ffblk *fnf;
int errflag=0;
FILE *f1;
fnf=(struct ffblk *)calloc(1,sizeof(struct ffblk));
head=(struct d_info *)calloc(1,sizeof(struct d_info));
dir=head;
dir->prev=head;
dir->next=head;
dir->f_inf=(struct ffblk *)calloc(1,sizeof(struct ffblk)+8);
errflag=findfirst(path,fnf,F_FLAG);
if(!errflag) {
if(!(fnf->ff_attrib & F_FLAG)) errflag=1;
tfiles++;
strlwr(fnf->ff_name);
memcpy(dir->f_inf,fnf,sizeof(struct ffblk));
while(!errflag) {
next=dir;
dir->next=(struct d_info *)calloc(1,sizeof(struct d_info));
dir=dir->next;
dir->next=head;
dir->prev=next;
head->prev=dir;
dir->f_inf=(struct ffblk *)calloc(1,sizeof(struct ffblk)+8);
errflag=findnext(fnf);
if(!errflag && !(fnf->ff_attrib & F_FLAG)) errflag=1;
if(!errflag) tfiles++; /* just to shut warning msg from tc */
strlwr(fnf->ff_name);
memcpy(dir->f_inf,fnf,sizeof(struct ffblk));
}
}
free(fnf);
return(head);
}
int setflags(flag,val) const int flag, val; {
switch(flag) {
case ALL_F:
case 0: Cf=val; if(flag != ALL_F) break;
case 1: Ff=val; if(flag != ALL_F) break;
case 2: Rf=val; if(flag != ALL_F) break;
case 3: af=val; if(flag != ALL_F) break;
case 4: bf=val; if(flag != ALL_F) break;
case 5: cf=val; if(flag != ALL_F) break;
case 6: df=val; if(flag != ALL_F) break;
case 7: ff=val; if(flag != ALL_F) break;
case 8: gf=val; if(flag != ALL_F) break;
case 9: If=val; if(flag != ALL_F) break;
case 10: lf=val; if(flag != ALL_F) break;
case 11: mf=val; if(flag != ALL_F) break;
case 12: nf=val; if(flag != ALL_F) break;
case 13: of=val; if(flag != ALL_F) break;
case 14: pf=val; if(flag != ALL_F) break;
case 15: qf=val; if(flag != ALL_F) break;
case 16: rf=val; if(flag != ALL_F) break;
case 17: sf=val; if(flag != ALL_F) break;
case 18: tf=val; if(flag != ALL_F) break;
case 19: uf=val; if(flag != ALL_F) break;
case 20: xf=val; if(flag != ALL_F) break;
case 21: zf=val;
}
return(TRUE);
}
int getflags(args) char *args; {
char tokens[23] = "CFRabcdfgilmnopqrstuxz";
int i, index, ind=FALSE;
if(args[0]=='-') {
for(i=1;i <= strlen(args);i++) {
===============================[ CHANGE THIS ]================================
if((index=istok(args[i],tokens))!=0) |
==============================================================================
====================================[ TO ]====================================
| if((index=istok(args[i],tokens))!=ERR_F) |
==============================================================================
Position '0' just happens to be the position of the 'C' flag and it was
returning an error back to the function and exiting the program.
ind=setflags(index,TRUE);
else nfexit(1,args[i]);
}
}
if(Cf && !xf) xf=Cf;
if(xf && !Cf) Cf=xf;
if(cf && !uf) uf=cf;
if(uf && !cf) cf=uf;
if(lf && cf && !tf) tf=1;
if(zf && tf) tf=0; /* the presence of =z flag negates =t flag */
if(cf && !tf) cf=0;
return(ind);
}
char *f_toke(path,fpath) char *path, *fpath; {
int i;
for(i=0;path[i]!=nil;i++) {
if(path[i]=='\\') strncpy(fpath,path,i+1);
}
return(fpath);
}
char *st_toke(path) char *path; {
int err;
struct ffblk fnf;
char *tmps;
err=findfirst(path,&fnf,FA_DIREC);
tmps=path;
for(;;tmps++) {
if(!strcmp(tmps,"*.*") || !strcmp(tmps,"?.?") ||
!strcmp(tmps,"*.?") || !strcmp(tmps,"?.*")) return(path);
if(!strcmp(tmps,"\\")) {
strcat(path,"*.*"); return(path);
}
if(!strcmp(tmps,"*") || !strcmp(tmps,"?")) {
strcat(path,".*"); return(path);
}
if(!strcmp(tmps,"*.") || !strcmp(tmps,"?.") || !strcmp(tmps,".")) {
strcat(path,"*"); return(path);
}
if(*tmps=='?') err = =1;
if(EOL(*tmps)) {
switch(err) {
case 0: strcat(path,"\\");
case =1: strcat(path,"*.*");
}
return(path);
}
}
}
int sort(ptr) struct d_info *ptr; {
struct d_info *d1;
struct d_info *d2;
void *d3;
if(ff) return(0); /* ff = fflag = =f (on command line) = no sorting */
d1=ptr;
if(!strcmp(d1->f_inf->ff_name,".")) d1=d1->next;
if(!strncmp(d1= f_inf->ff_name,"..",1)) d1=d1->next;
for(;d1!=ptr= prev;d1=d1->next)
for(d2=ptr= prev->prev;d2!=d1->prev;d2=d2->prev) {
if((!rf &&
((!tf && !zf &&
strcmp(d1= f_inf->ff_name,d2->f_inf->ff_name) > 0) ||
(!zf && !cf && tf &&
d1= f_inf->ff_fdate > d2->f_inf->ff_fdate) ||
(!zf && cf && tf &&
d1= f_inf->ff_ftime > d2->f_inf->ff_ftime) ||
(zf && !cf && !tf &&
d1= f_inf->ff_fsize > d2->f_inf->ff_fsize))) ||
(rf &&
((!tf && !zf &&
strcmp(d1= f_inf->ff_name,d2->f_inf->ff_name) < 0) ||
(!zf && !cf && tf &&
d1= f_inf->ff_fdate < d2->f_inf->ff_fdate) ||
(!zf && cf && tf &&
d1= f_inf->ff_ftime < d2->f_inf->ff_ftime) ||
(zf && !cf && !tf &&
d1= f_inf->ff_fsize < d2->f_inf->ff_fsize)))) {
d3=(void *)(d1= f_inf);
d1= f_inf=d2->f_inf;
(void *)(d2= f_inf)=d3;
}
}
return(0);
}
struct d_info *d_inc(ptr) struct d_info *ptr; {
char *str;
struct d_info *p1=0L;
p1=ptr;
str=ptr= f_inf->ff_name;
if(!strcmp(str,".")) {
ptr=ptr= next;
ptr= prev=p1->prev;
p1= prev->next=ptr;
free(p1); /* drat = a hole in memory */
p1=ptr;
==tfiles;
}
str=ptr= f_inf->ff_name;
if(!strcmp(str,"..")) {
ptr=ptr= next;
ptr= prev=p1->prev;
p1= prev->next=ptr;
free(p1); /* double drat = another hole in memory */
==tfiles;
}
return(ptr);
}
main(argc,argv) int argc; char **argv; {
int i=0;
struct d_info *dir;
fpath=(char *)calloc(1,128);
path=(char *)calloc(1,215);
F_FLAG=FA_ALL;
setflags(ALL_F,0);
if(argc == 2) {
if(argv[1][0]=='-') {
getflags(argv[1]);
strcpy(path,"*.*");
}
else strcpy(path,argv[1]);
}
if(argc = 3) {
for(i=1;i<=argc=2;i++)
if(argv[i][0]=='-')
getflags(argv[i]);
strcpy(path,argv[argc=1]);
}
if(Rf) printf("\nls: option =R not yet implemented.\n");
path=st_toke(path);
fpath=f_toke(path,fpath);
if(af) F_FLAG=FA_ALLF;
if(df) F_FLAG=FA_DIREC;
head=getdirstruct();
if(!af) head=d_inc(head); /* no . and .. unless =a is used */
sort(head);
dir=head;
crlf();
printf("total %d\n",tfiles);
while((dir= next != head) && (dir->next != NULL)) {
ff_stat(dir,&f_stat);
if((gf || If || lf || nf || of || sf) && !Cf) {
if(If) pr_inode();
if(sf) pr_block(dir);
pr_stat(dir);
if(gf || lf || nf || of) pr_links();
if(lf || of || nf) pr_uid(dir);
if(lf || gf || nf) pr_gid(dir);
pr_size(dir);
pr_date(dir);
pr_time(dir);
}
=============================[ CHANGE THIS ]==============================
pr_name(dir); |
if(!Cf) {crlf(); i=0; } |
if(Cf && i%5 == 4) crlf(); |
i++; |
==========================================================================
=================================[ TO ]===================================
| pr_name(dir,i); |
| if(!Cf) crlf(); |
| else if(i++ % 5 == 4) { crlf(); i=0; } |
==========================================================================
The pr_name() function was printing sloppy lines when the "C" or "x" flags
were used at the program startup. So "i" was included as a parameter to
pr_name() to determine the modulo of 5 (see added notes under function
pr_name() above).
dir=dir->next;
if(dir->next==head) break;
}
if(tfiles==0) printf("%s: file not found\n",path);
}
============================ end of file =====================================
Darrell (mangor@disk.uucp)
Technical Details
Message-ID:
<4066@disk.UUCP>Path:
arc1-ca.pugleaf.net!utzoo!attcan!uunet!know!samsung!zaphod.mps.ohio-state.edu!usc!apple!olivea!orc!inews!iwarp.intel.com!gargoyle!igloo!ddsw1!corpane!disk!mangorShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!uunet!know!samsung!zaphod.mps.ohio-state.edu!usc!apple!olivea!orc!inews!iwarp.intel.com!gargoyle!igloo!ddsw1!corpane!disk!mangor From: mangor@disk.UUCP (Darrell Kitchen) Newsgroups: comp.os.msdos.programmer Subject: Re: ls.c Message-ID: <4066@disk.UUCP> Date: 5 Sep 90 18:39:24 GMT Reply-To: mangor@disk.UUCP (Darrell Kitchen) Distribution: comp.os.msdos.apps, comp.os.msdos.mics, comp.os.msdos.programmer Organization: DISK, Louisville Ky Lines: 550