Unix LS for the IBM PC, with many options
Bernie Roehl
broehl at watale.UUCP
Sun Aug 24 09:36:03 AEST 1986
This is a version of the Unix LS program for the Ibm Pcs with many
different options. Have fun with it.
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by watale!broehl on Sat Aug 23 19:30:13 EDT 1986
# Contents: ctlc.c isatty.c ls.c ptext.c read.me
echo x - ctlc.c
sed 's/^@//' > "ctlc.c" <<'@//E*O*F ctlc.c//'
#include <stdio.h>
#include <signal.h>
static process_sigint()
{
/* Buffers aren't flushed when a ^C is encountered by.
* dos. Since exit() does do a buffer flush so re arange
* to call exit on intercepting a ^C
*/
exit( 1 );
}
ctlc()
{
/* Make control-C behave intellegently
*/
signal(SIGINT, process_sigint );
}
@//E*O*F ctlc.c//
chmod u=rw,g=r,o=r ctlc.c
echo x - isatty.c
sed 's/^@//' > "isatty.c" <<'@//E*O*F isatty.c//'
/* Return non-zero if the specified handle refers to a device */
/* Written by Bernie Roehl, July 1986 */
#define LINT_ARGS
#include <stdio.h>
#include <dos.h>
#include "masdos.h"
int isatty()
{
struct REGS regs;
regs.h.ah = 0x44;
regs.h.al = 0x00;
regs.x.bx = 0x0001;
int86( I_BDOS, ®s, ®s );
return( (int) regs.x.dx & IO_ISDEV );
}
@//E*O*F isatty.c//
chmod u=rw,g=r,o=r isatty.c
echo x - ls.c
sed 's/^@//' > "ls.c" <<'@//E*O*F ls.c//'
/*
*
*!AU: Michael A. Shiels
*!CD: 1-Jun-86
*!FR: Dr. Dobbs July 1985
*
*/
#define LINT_ARGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <malloc.h>
#include "getargs.h"
#include "masdos.h"
#define MAXDIR 500
#define EOS(s) while(*s) s++
static int Arg_Long_Fmt = 0;
static int Arg_Unsorted = 0;
static int Arg_Files_Only = 0;
static int Arg_No_Graphics = 0;
static int Arg_Dirs_Only = 0;
static int Arg_List_All = 0;
static int Arg_Num_Cols = 5;
static int Arg_Ext_Sort = 0;
static int Arg_Time_Sort = 0;
static int Arg_Size_Sort = 0;
static int Arg_Exp_Dir = 1;
static int Arg_Mul_Exp = 0;
static int Arg_Debug = 0;
static int Arg_Back_Sort = 0;
static int Arg_Vert_Prt = 0;
void usage()
{
fprintf( stderr, "Usage: ls [%c[ABDEFLMNSTUVX][C<num>][Z]] [files]...\n", ARG_Switch );
fprintf( stderr, "\n");
fprintf( stderr, "Set the environment variable SWITCHAR to the character\n");
fprintf( stderr, "you wish to use for the Switch Character\n");
fprintf( stderr, "\n" );
fprintf( stderr, "Case of the command line switches %s important\n",
ARG_ICase ? "is not" : "is" );
fprintf( stderr, "\n" );
}
ARG Argtab[] =
{
{ 'A', ARG_FBOOLEAN, &Arg_List_All, "List all files (hidden to)" },
{ 'B', ARG_FBOOLEAN, &Arg_Back_Sort, "Backwards sort (reverse)" },
{ 'C', ARG_INTEGER, &Arg_Num_Cols, "Number of Columns" },
{ 'D', ARG_FBOOLEAN, &Arg_Dirs_Only, "Directories Only" },
{ 'E', ARG_FBOOLEAN, &Arg_Ext_Sort, "Sort by Extension" },
{ 'F', ARG_FBOOLEAN, &Arg_Files_Only, "Files Only" },
{ 'L', ARG_FBOOLEAN, &Arg_Long_Fmt, "Long Format" },
{ 'M', ARG_FBOOLEAN, &Arg_Mul_Exp, "Expand multiple parameters" },
{ 'N', ARG_FBOOLEAN, &Arg_No_Graphics, "Suppress ANSI graphics" },
{ 'S', ARG_FBOOLEAN, &Arg_Size_Sort, "Sort by File Size" },
{ 'T', ARG_FBOOLEAN, &Arg_Time_Sort, "Sort by Date and Time" },
{ 'U', ARG_FBOOLEAN, &Arg_Unsorted, "Suppress Sorting" },
{ 'V', ARG_FBOOLEAN, &Arg_Vert_Prt, "Print Vertically" },
{ 'X', ARG_TBOOLEAN, &Arg_Exp_Dir, "Expand single directories" },
{ 'Z', ARG_FBOOLEAN, &Arg_Debug, "Debug Mode" }
};
#define ARG_TABSIZE ( sizeof(Argtab) / sizeof(ARG) )
static char *Dirs[MAXDIR];
static char **Dirv = Dirs;
static int Dirc = 0;
static long Total = 0L;
static int Numfiles = 0;
static int Numdirs = 0;
static struct FILEINFO *dta_save;
static struct FILEINFO *dta1;
argvcmp( s1p, s2p )
char **s1p, **s2p;
{
int ercode;
D_IN("argvcmp");
ercode = strcmp( *s1p, *s2p );
D_OUT("argvcmp");
return( ercode );
}
scmp( s1p, s2p )
char **s1p, **s2p;
{
char *s1, *s2;
int c1,c2;
int rval;
s1 = *s1p;
s2 = *s2p;
if(!Arg_No_Graphics && *s1 == Q_ESC)
for( c1 = 1 ; c1 <= 8 ; s1++, c1++ );
if(!Arg_No_Graphics && *s2 == Q_ESC)
for( c2 = 1 ; c2 <= 8 ; s2++, c2++ );
for( c1 = 1 ; c1 <= 13 ; s1++, c1++ );
for( c2 = 1 ; c2 <= 13 ; s2++, c2++ );
if( rval = strncmp( s1, s2, 6 ) )
return rval;
rval = strcmp( *s1p, *s2p );
return( rval );
}
tcmp( s1p, s2p )
char **s1p, **s2p;
{
char *s1, *s2;
int c1,c2;
int rval;
s1 = *s1p;
s2 = *s2p;
if(!Arg_No_Graphics && *s1 == Q_ESC)
for( c1 = 1 ; c1 <= 8 ; s1++, c1++ );
if(!Arg_No_Graphics && *s2 == Q_ESC)
for( c2 = 1 ; c2 <= 8 ; s2++, c2++ );
for( c1 = 1 ; c1 <= 20 ; s1++, c1++ );
for( c2 = 1 ; c2 <= 20 ; s2++, c2++ );
rval = strncmp( s1, s2, 17 );
return( rval * -1 );
}
ecmp( s1p, s2p )
char **s1p, **s2p;
{
char *s1, *s2;
int c1,c2;
int rval;
for( s1 = *s1p, c1 = 1 ; *s1 && *s1 != '.' && *s1 != ' ' ; s1++, c1++ );
for( s2 = *s2p, c2 = 1 ; *s2 && *s2 != '.' && *s2 != ' ' ; s2++, c2++ );
if( rval = strncmp( s1, s2, min(c1,c2 ) ) )
return rval;
for( s1 = *s1p, s2 = *s2p ; *s1 == *s2 && *s1 && *s1 != '.' ; s1++, s2++ );
return( ( *s1 == '.' ? 0 : *s1 ) - ( *s2 == '.' ? 0 : *s2 ) );
}
comp( s1p, s2p )
char **s1p, **s2p;
{
int ercode;
D_IN("comp");
if(Arg_Ext_Sort)
{
ercode = ecmp( s1p, s2p );
D_OUT("comp(ecmp)");
return( Arg_Back_Sort ? ercode * -1 : ercode );
}
else
{
if(Arg_Time_Sort)
{
ercode = tcmp( s1p, s2p );
D_OUT("comp(tcmp)");
return( Arg_Back_Sort ? ercode * -1 : ercode );
}
else
{
if( Arg_Size_Sort )
{
ercode = scmp( s1p, s2p );
D_OUT("comp(ssrt)");
return( Arg_Back_Sort ? ercode * -1 : ercode );
}
else
{
ercode = argvcmp( s1p, s2p );
D_OUT("comp(argvcmp)");
return( Arg_Back_Sort ? ercode * -1 : ercode );
}
}
}
}
void set_dta( dta )
struct FILEINFO *dta;
{
struct REGS regs;
D_IN("set_dta");
regs.x.ax = B_GETDTA;
intdos( ®s, ®s );
dta_save = (struct FILEINFO *) regs.x.bx;
regs.x.ax = B_SETDTA;
regs.x.dx = (unsigned int) dta;
intdos( ®s, ®s );
D_OUT("set_dta");
}
void reset_dta( )
{
struct REGS regs;
D_IN("reset_dta");
regs.x.ax = B_SETDTA;
regs.x.dx = (unsigned int) dta_save;
intdos( ®s, ®s );
D_OUT("reset_dta");
}
find_first( filespec, attributes, dta )
char *filespec;
unsigned int attributes;
struct FILEINFO *dta;
{
struct REGS regs;
int ercode;
D_IN("find_first");
set_dta( dta );
regs.x.ax = B_FINDFIRST;
regs.x.dx = (int) filespec;
regs.x.cx = attributes;
ercode = intdos( ®s, ®s );
reset_dta();
if( ercode == 0 )
{
D_S("find_first","dta->fi_name=",dta->fi_name);
D_PRT("find_first","no error");
}
D_OUT("find_first");
return( ercode );
}
int find_next( dta )
struct FILEINFO *dta;
{
struct REGS regs;
int ercode;
D_IN("find_next");
set_dta( dta );
regs.x.ax = B_FINDNEXT;
ercode = intdos( ®s, ®s );
reset_dta();
if( ercode == 0 )
{
D_S("find_next","dta->fi_name=",dta->fi_name);
D_PRT("find_next","no error");
}
D_OUT("find_next");
return( ercode );
}
dirtoa( s, p )
char *s;
struct FILEINFO *p;
{
char *startstr = s;
int i;
D_IN("dirtoa");
D_S("dirtoa","p->fi_name=",p->fi_name);
if ( !Arg_No_Graphics && ( IS_LABEL(p) || IS_SUBDIR(p) ) )
sprintf( s, "%s%s%s", IS_LABEL(p) ? P_REVERSE : P_BOLDFACE,
p->fi_name, P_ALL_OFF );
else
sprintf( s, "%s", p->fi_name );
EOS(s);
if( Arg_Long_Fmt )
{
for( i = strlen(p->fi_name) ; i++ < 12 ; *s++ = ' ' );
sprintf( s, " %6ld ", p->fi_fsize );
EOS(s);
sprintf( s, "%2d-%02d-%02d %2d:%02d:%02d",
C_YEAR(p)-1900, C_MONTH(p), C_DAY(p),
C_HOUR(p), C_MIN(p), C_SEC(p));
s += 17;
*s++ = ' ';
if( IS_READONLY(p) ) { *s++ = 'r'; } else { *s++ = '.'; }
if( IS_HIDDEN(p) ) { *s++ = 'h'; } else { *s++ = '.'; }
if( IS_SYSTEM(p) ) { *s++ = 's'; } else { *s++ = '.'; }
if( IS_LABEL(p) ) { *s++ = 'l'; } else { *s++ = '.'; }
if( IS_SUBDIR(p) ) { *s++ = 'd'; } else { *s++ = '.'; }
if( IS_DIRTY(p) ) { *s++ = 'm'; } else { *s++ = '.'; }
*s = 0;
}
D_OUT("dirtoa");
return( s - startstr );
}
haswild( s )
char *s;
{
D_IN("haswild");
for( ; *s ; s++ )
if( *s == '*' || *s == '?' )
{
D_S("haswild","filename=","wildcharacters");
D_OUT("haswild");
return 1;
}
D_OUT("haswild");
return 0;
}
printdir( dirc, dirv )
int dirc;
char **dirv;
{
D_IN("printdir");
if( !Arg_Unsorted )
qsort( dirv, dirc, sizeof(*dirv), comp);
if( Arg_Vert_Prt )
ptextv( dirc, dirv, Arg_Num_Cols, 79 / Arg_Num_Cols,
(dirc/Arg_Num_Cols) + (dirc % Arg_Num_Cols != 0) );
else
ptexth( dirc, dirv, Arg_Num_Cols, 79 / Arg_Num_Cols,
(dirc/Arg_Num_Cols) + (dirc % Arg_Num_Cols != 0) );
D_OUT("printdir");
}
char *fixup_name( name, dta )
char *name;
struct FILEINFO *dta;
{
static char buf[80], *p;
D_IN("fixup_name");
if( !find_first( name, A_SUBDIR, dta ) && Arg_Exp_Dir )
{
D_S("fixup_name","dta->fi_name=",dta->fi_name);
if( !IS_SUBDIR(dta) )
{
D_S("fixup_name","newname=",name);
D_PRT("fixup_name","no name change");
D_OUT("fixup_name");
return( name );
}
strncpy( buf, name, 80 );
strncat( buf, "\\*.*", 80 );
D_S("fixup_name","newname=",buf);
D_PRT("fixup_name","directory");
D_OUT("fixup_name");
return( buf );
}
else
{
if( name[1] == ':' )
{
buf[0] = name[0];
buf[1] = ':';
if( !*(name += 2) )
{
buf[2] = '*';
buf[3] = '.';
buf[4] = '*';
buf[5] = 0;
D_S("fixup_name","newname=",buf);
D_PRT("fixup_name","disk");
D_OUT("fixup_name");
return( buf );
}
else
buf[2] = 0;
}
for( p = name ; *p ; p++ )
if( !( *p == '.' || *p == '\\' || *p == '/' ) )
{
D_S("fixup_name","newname=",name);
D_PRT("fixup_name",". or \\ or /");
D_OUT("fixup_name");
return( name );
}
strncat( buf, "\\*.*", 80 );
D_S("fixup_name","newname=",buf);
D_PRT("fixup_name","fall through");
D_OUT("fixup_name");
return( buf );
}
}
add_entry( dta )
struct FILEINFO *dta;
{
char buf[64];
register int strlen;
D_IN("add_entry");
if( !Arg_List_All && ( IS_HIDDEN(dta) || *dta->fi_name == '.') )
{
D_PRT("add_entry","Not /A but hidden/.");
D_OUT("add_entry");
return 1;
}
if( IS_SUBDIR(dta) )
{
Numdirs++;
}
else if( Arg_Dirs_Only )
{
D_PRT("add_entry","only directories");
D_OUT("add_entry");
return 1;
}
else if( !IS_LABEL(dta) )
{
Numfiles++;
}
strlen = dirtoa( buf, dta );
if( ++Dirc > MAXDIR || !( *Dirv = malloc( strlen + 1 ) ) )
{
D_PRT("add_entry","too many dirs or malloc");
D_OUT("add_entry");
return 0;
}
strcpy( *Dirv++, buf );
Total += dta->fi_fsize;
D_PRT("add_entry","entry added");
D_OUT("add_entry");
return 1;
}
main( argc, argv )
int argc;
char **argv;
{
static char *name = "*.*";
D_IN("main");
ctlc();
ARG_ICase = 1;
argc = getargs( argc, argv, Argtab, ARG_TABSIZE );
if( Arg_Time_Sort || Arg_Size_Sort )
Arg_Long_Fmt = 1;
if( Arg_Long_Fmt )
Arg_Num_Cols = 1;
if( !isatty() )
Arg_No_Graphics = 1;
if( argc >= 2 )
{
name = *(++argv);
if( argc == 2 && !haswild( name ) && !Arg_Mul_Exp )
name = fixup_name( name, &dta1 );
}
do
{
if( !haswild( name ) && Arg_Mul_Exp )
name = fixup_name( name, &dta1 );
if( !find_first( name, Arg_Files_Only ? A_ALL_FILES : A_ALL,
&dta1 ) )
{
if( !add_entry( &dta1 ) )
break;
if( haswild( name ) )
while( !find_next( &dta1 ) )
if( !add_entry( &dta1 ) )
goto abort;
}
name = *(++argv);
} while ( --argc > 1 );
abort: if(Dirc != 0)
printf("\n");
printdir( Dirc, Dirs );
if(Dirc != 0)
printf("\n");
if( Numfiles )
{
printf("%d file%s (%ld bytes, %d K)",
Numfiles, Numfiles == 1 ? "" : "s",
Total, Total/1024 );
}
if( Numdirs )
{
if( Numfiles )
printf(", ");
printf("%d director%s", Numdirs, Numdirs == 1 ? "y" : "ies" );
}
printf("\n");
D_OUT("main");
}
@//E*O*F ls.c//
chmod u=rw,g=r,o=r ls.c
echo x - ptext.c
sed 's/^@//' > "ptext.c" <<'@//E*O*F ptext.c//'
/*
*
*!AU: Michael A. Shiels
*!CD: 1-Jun-86
*!FR: Dr. Dobbs July 1985
*
*/
#define LINT_ARGS
#include <stdio.h>
#include "masdos.h"
#define PTEXT_IBM
/* ptext( dirc, dirv, Arg_Num_Cols, 79 / Arg_Num_Cols,
(dirc/Arg_Num_Cols) + (dirc % Arg_Num_Cols != 0) ); */
ptexth( linec, linev, numcols, colwidth, numrows )
int linec, numcols, colwidth;
char **linev;
int numrows;
{
register int j,i;
register char **lineend, **line, **nextline;
D_IN("ptexth");
D_I("ptexth","numcols=",numcols);
D_I("ptexth","colwidth=",colwidth);
D_I("ptexth","numrows=",numrows);
lineend = &linev[linec - 1];
for( j = numrows ; --j >= 0 ; )
{
#ifdef PTEXT_IBM
putchar( ' ' );
#endif
for( i = numcols ; --i >= 0 && *linev ; linev++ )
{
pr_line( *linev, colwidth,
linev <= lineend );
}
printf( "\n" );
}
D_OUT("ptexth");
}
ptextv( linec, linev, numcols, colwidth, numrows )
int linec, numcols, colwidth;
char **linev;
int numrows;
{
register int j;
register char **lineend, **line, **nextline;
D_IN("ptextv");
D_I("ptextv","numcols=",numcols);
D_I("ptextv","colwidth=",colwidth);
D_I("ptextv","numrows=",numrows);
lineend = &linev[linec - 1];
for( j = numrows ; --j >= 0 ; )
{
#ifdef PTEXT_IBM
putchar( ' ' );
#endif
for( line = linev++ ; line <= lineend ; line = nextline )
{
nextline = line + numrows;
pr_line( *line, colwidth,
nextline <= lineend );
}
printf( "\n" );
}
D_OUT("ptextv");
}
static pr_line( str, width, padded )
register char *str;
int width, padded;
{
int col = 0;
while( col < width && *str )
{
if( *str == '\n' )
break;
else if( *str == '\r' )
{
while( col > 0 )
{
--col;
putchar( '\b' );
}
str++;
}
else if( *str == '\t' )
{
str++;
col++;
putchar( ' ' );
while( ( col % 8 ) && col < width )
{
putchar( ' ' );
col++;
}
}
else if( *str == Q_ESC )
{
putchar( *str++ );
if( !*str )
break;
putchar( *str++ );
if( !*str )
break;
putchar( *str++ );
if( !*str )
break;
putchar( *str++ );
if( !*str )
break;
}
else if( *str == '\b' )
--col;
else if( *str == ' ' )
++col;
putchar( *str++ );
++col;
}
if( padded )
while( col++ < width )
putchar( ' ' );
}
@//E*O*F ptext.c//
chmod u=rw,g=r,o=r ptext.c
echo x - read.me
sed 's/^@//' > "read.me" <<'@//E*O*F read.me//'
These files make up an expanded version of the UNIX utility LS. Another
version will be out soon which will have recursion down directories.
This posting also needs a subroutine out of the LIBRARY posting.
@//E*O*F read.me//
chmod u=rw,g=r,o=r read.me
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
22 54 331 ctlc.c
18 55 349 isatty.c
518 1637 13647 ls.c
141 355 3836 ptext.c
5 35 209 read.me
704 2136 18372 total
!!!
wc ctlc.c isatty.c ls.c ptext.c read.me | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0
--
Michael A. Shiels
clyde-\
decvax-\\
ihnp4-\\\
+++-----> watmath!watale!broehl
tektronix-///
ubc-vision-//
utzoo-/
More information about the Comp.sources.unix
mailing list