broehl@watale.UUCP (Bernie Roehl) (08/24/86)
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-/