#ifdef ournix #include "ournix.h" #endif char sccsID[] = "@(#) ls.c V2.0 Copyright VSL(pjc+jhs) 1987\n" ; /* ls - Unix like ls for MSDOS */ #include #include #include #ifdef MSDOS #include "ndir.h" #else #include #endif extern DIR *opendir() ; extern struct direct *readdir() ; extern void closedir() ; #define ENOUGH 128 #define MAXDIR 1024 struct mlist { char m_name[12+2]; long m_size; short m_mode; long m_time; }; struct mlist *m_tab[MAXDIR]; struct mlist **m_end; struct mlist **m_start; struct mlist *m_stat(); int tom_stat; char *malloc(); char aflag; char Rflag; char rflag; char lflag; char tflag; char xflag; char nomem; char oneflag; char Cflag; char dflag; char Fflag; char Xflag; char Dflag; char **ARGV ; main(argc, argv) char **argv; { char *opt; int status = 0; int flag = 0; ARGV = argv ; #ifdef VSL /* { */ #include "../../include/vsl.h" #endif /* } */ for(argv++, argc--; argc ; argc--, argv++){ if(*(opt = *argv) != '-') break; while(*++opt) switch(*opt){ case 'D': Dflag = 1; break; case 'd': dflag = 1; break; case 'X': /* NOT UNIX */ Xflag = 1; break; case 'r': rflag = 1; break; case 'F': Fflag = 1; break; case '1': oneflag = 1; break; case 'C': Cflag = 1; break; case 'a': case 'A': aflag = 1; break; case 'R': Rflag = 1; break; case 'l': lflag = 1; break; case 't': tflag = 1; break; case 'x': xflag = 1; break; } } if(!oneflag){ if(!Cflag && !isatty(1)) oneflag = 1; } if(lflag) oneflag = 1; if(Xflag || lflag) xflag = 1; if(oneflag) xflag = 1; tom_stat = (lflag || Rflag || Xflag || Dflag || tflag || Fflag); if(argc <= 0) status = doit(".", 0); else for(flag = (argc > 1); argc ; argc--, argv++) status |= doit(*argv, flag); exit(status); } doit(d, flag) char *d; { struct mlist *mp; struct stat statbuf; int status; if(stat(d, &statbuf) < 0){ status = rootchk(d, flag); if(status >= 0) return(status); mp = m_stat(d, 0, (struct stat *)0, 1); } else mp = m_stat(d, 0, &statbuf, 1); if(mp == NULL) return(1); if((mp->m_mode & S_IFMT) != S_IFDIR || dflag){ if(!Dflag || dflag){ if(lflag) lprint(mp, d); else printit(mp, d, 1); } free( (char *)mp); return(0); } free( (char *)mp); if(flag) printf("%s:\n", d); m_start = m_tab; /* put start at start of table */ if(status = recurse(d)) return(status); if(flag) printf("\n"); return(0); } /* * check to see if directory is root */ rootchk(d, flag) char *d; { DIR *dirp; static char NULLS[] = ""; char **xp; static char *matches[] = { ".", "/", "\\", (char *)0, }; for(xp = matches ; *xp ; xp++) if(strcmp(d, *xp) == 0){ dirp = opendir(NULLS); /* "" for ROOT ?? */ if(dirp == NULL) return(-1); closedir(dirp); if(flag) printf("%s\n", d); m_start = m_tab; /* get start right */ return(recurse(NULLS)); } return(-1); } recurse(d) char *d; { int nentries; int nc; struct mlist *mp, **xmp; struct mlist **Mp; char *tbuf; int nlp; int nlines; nentries = dirbuild(d); if(nentries < 0) return(1); else if(nentries == 0) return(0); nc = 0; if(xflag){ for(Mp = m_start ; Mp < m_end ;){ mp = *Mp++; if(Dflag && (mp->m_mode & S_IFMT ) != S_IFDIR){ if(!Rflag) free( (char *)mp); continue; } nc = ++nc % 5; if(Xflag){ if( (mp->m_mode & S_IFMT) != S_IFDIR) #ifdef unix /* { */ #define DIR_DELIM '/' #endif /* } */ #ifdef MSDOS /* { */ #define DIR_DELIM '\\' #endif /* } */ printf("%s%c%s\n", d,DIR_DELIM, mp->m_name); } else if(lflag) lprint(mp, mp->m_name); else printit(mp, mp->m_name, oneflag || !nc || Mp == m_end); if(!Rflag) free( (char *)mp); } } else { /* must sort into 5 column output */ nlines = (nentries + 4) / 5; for(nlp = 0; nlp < nlines ; nlp++){ for(nc = 0 ; nc < 5 ; nc++){ Mp = m_start + nlp + (nlines*nc); if(Mp >= m_end) break; mp = *Mp; nentries--; if(Dflag && (mp->m_mode & S_IFMT ) != S_IFDIR){ if(!Rflag) free( (char *)mp); continue; } printit(mp, mp->m_name, (nc==4) || !nentries); if(!Rflag) free( (char *)mp); } } } if(!Rflag) return(0); for(Mp = m_start ; Mp < m_end ;){ mp = *Mp++; if((mp->m_mode & S_IFMT) == S_IFDIR && !dot(mp->m_name)){ tbuf = malloc(strlen(d) + strlen(mp->m_name) + 2); if(tbuf != 0){ sprintf(tbuf, "%s%c%s", d, DIR_DELIM, mp->m_name); if(!Xflag && !Dflag) printf("\n%s:\n",tbuf); xmp = m_start; m_start = m_end; if(recurse(tbuf)){ m_end = m_start; m_start = xmp; free(tbuf); return(1); } m_end = m_start; m_start = xmp; free(tbuf); } } free( (char *)mp); } return(0); } dirbuild(d) char *d; { DIR *dirp; struct direct *dp; struct mlist *mp; static char tbuf[ENOUGH]; int n = 0; m_end = m_start; dirp = opendir(d); if(dirp == 0){ fprintf(stderr, "Cannot open '%s'\n", d); return(-1); } strcpy(tbuf, d); d = &tbuf[strlen(d)]; *d++ = DIR_DELIM ; while((dp = readdir(dirp)) != NULL){ if(!aflag && dot(dp->d_name)) continue; strcpy(d, dp->d_name); mp = m_stat(tbuf, dp->d_name, (struct stat *)0, tom_stat); if(mp == 0){ if(nomem) break; continue; } *m_end++ = mp; if(m_end > &m_tab[MAXDIR-1]){ fprintf(stderr, "Out of memory\n"); nomem = 1; break; } } closedir(dirp); n = m_end - m_start; sortit(m_start, n); return(n); } dot(name) char *name; { if(*name != '.') return(0); if(name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return(1); return(0); } struct mlist * m_stat(nam, pnam, statp, tostat) char *nam, *pnam; struct stat *statp; { struct stat statbuf; struct mlist *mp; if(statp == (struct stat *)0 && tostat){ statp = &statbuf; if(stat(nam, statp) < 0){ fprintf(stderr, "Can't stat '%s'\n", nam); return(0); } } mp = (struct mlist *)malloc(sizeof(struct mlist)); if(mp == 0){ if(!nomem) fprintf(stderr, "Out of memory\n"); nomem = 1; return(0); } if(pnam) strcpy(mp->m_name, pnam); else mp->m_name[0] = '\0'; if(tostat){ mp->m_size = statp->st_size; mp->m_mode = statp->st_mode; mp->m_time = statp->st_mtime; } return(mp); } asccomp(a1, a2) struct mlist **a1, **a2; { if(rflag) return(strcmp((*a2)->m_name, (*a1)->m_name)); else return(strcmp((*a1)->m_name, (*a2)->m_name)); } timcomp(a1, a2) struct mlist **a1, **a2; { if((*a1)->m_time == (*a2)->m_time) return(0); if(rflag){ if((*a1)->m_time > (*a2)->m_time) return(1); } else if((*a1)->m_time < (*a2)->m_time) return(1); return(-1); } sortit(m_tab, n) struct mlist **m_tab; { int (*cmpfunc)(); if(!n) return; if(tflag) cmpfunc = timcomp; else cmpfunc = asccomp; qsort((char *)m_tab, n, sizeof(struct mlist *), cmpfunc); } /* * do an ls -l type of printing */ lprint(mp, nam) struct mlist *mp; char *nam; { char tbuf[12]; char *sp; int i, mode; char *ctime(); if(nam == 0) nam = mp->m_name; sp = tbuf; mode = mp->m_mode; if((mode & S_IFMT) == S_IFDIR) *sp++ = 'd'; else *sp++ = '-'; for(i = 0 ; i < 3 ; i++, mode<<=3){ if(mode & S_IREAD) *sp++ = 'r'; else *sp++ = '-'; if(mode & S_IWRITE) *sp++ = 'w'; else *sp++ = '-'; if(mode & S_IEXEC) *sp++ = 'x'; else *sp++ = '-'; } *sp = 0; sp = ctime(&mp->m_time) + 4; printf("%s %-16s %-7ld %20.20s\n", tbuf, nam, mp->m_size, sp); } printit(mp, xnam, flag) struct mlist *mp; char *xnam; { char *cstr = ""; char lbuf[20]; if(Fflag){ switch(mp->m_mode & S_IFMT){ case S_IFDIR: cstr = "/"; break; default: if(mp->m_mode & S_IEXEC) cstr = "*"; break; } } if(xnam == 0) xnam = mp->m_name; sprintf(lbuf, "%s%s", xnam, cstr); if(flag) printf("%s\n", lbuf); else printf("%-16s", lbuf); }