shell for MS-DOS (part 3 - utilities)
Douglas Orr
doug at umich.UUCP
Mon Aug 5 04:15:17 AEST 1985
Here is part 3 of the Unix-like shell for DOS. This part contains
some DOS utilities.
-Doug
{ihnp4,mb2c,pur-ee}!umich!textset!doug
doug%textset at umich.csnet
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# cp.c
# more.c
# fgrep.c
# This archive created: Sun Aug 4 14:02:56 1985
cat << \SHAR_EOF > cp.c
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys\types.h>
#include <sys\stat.h>
#define Usage "usage: %s file1 file2\n\tor %s file1 file2 ... [dir|dev:]\n"
main( argc, argv )
int argc;
char * argv[];
{
struct stat statb;
int dir;
char * dest;
char dbuf[256];
static char buf[30*BUFSIZ];
int ifd, ofd;
int cnt;
int mv;
char * pgm;
char * ptr;
int ident;
pgm = argv[0];
if( argc < 3 )
{
usage:
fprintf( stderr, Usage, pgm, pgm );
exit(1);
}
/* is this "mv" or "cp"? */
strlwr( pgm );
if( (ptr = strrchr( pgm, '\\' )) == NULL)
ptr = pgm;
else
++ptr;
mv = (strcmp( ptr, "mv.exe" ) == 0)
|| (strcmp( ptr, "mv" ) == 0);
/* is this cp a b, or cp a b c <dir/dev:>? */
dest = argv[--argc];
if( (stat( dest, &statb ) == -1
|| !((statb.st_mode & S_IFDIR)
|| (strcmp( dest, "\\" ) == 0))) /* msdos sucks */
&& !((strlen(dest) == 2) && (dest[1] == ':')) )
dir = 0;
else
dir = 1;
if( strcmp( dest, "." ) == 0 )
ident = 1;
else
ident = 0;
if( (argc > 2) && !dir )
goto usage;
/*
* move or copy all of the files on the arg list
*/
while( --argc )
{
++argv;
if( ident )
{
/* I hate ms-dos */
if( (ptr = strrchr( *argv, '\\' )) == NULL
&& (ptr = strrchr( *argv, '/')) == NULL )
{
fprintf( stderr, "can't copy %s onto itself\n", *argv );
exit( 1 );
}
strcpy( dbuf, ptr+1 );
}
else
if( dir )
sprintf( dbuf, "%s\\%s", dest, *argv );
else
strcpy( dbuf, dest );
if( (ifd = open( *argv, O_RDONLY+O_BINARY )) < 0 )
{
perror( pgm );
exit(1);
}
if( (ofd = open( dbuf, O_WRONLY+O_CREAT+O_TRUNC+O_BINARY, 0666 )) < 0 )
{
perror( pgm );
exit(1);
}
while( (cnt = read( ifd, buf, sizeof(buf) )) > 0 )
{
if( (cnt = write( ofd, buf, cnt )) < 0 )
break;
}
close(ifd);
close(ofd);
if( cnt < 0 )
{
/* I/O error */
perror( pgm );
exit( 1 );
}
if( mv )
unlink( *argv );
}
exit(0);
}
SHAR_EOF
cat << \SHAR_EOF > more.c
#include "gen.h"
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dos.h>
/*
* more: a Unix(tm) like more command for MS-DOS
*
* by Douglas Orr
* Textset Inc.
* Ann Arbor, Michigan
*
* Copyright (c) 1985 Textset. All rights reserved.
*
* This program may be freely distributed, but not sold for profit.
*
*/
/*
* To compile: msc -Ze more.c
*
* Code in chin must be changed if you go to a large memory model.
*/
Local char esc = '\033';
Local char ctl_z = '\032';
Local FILE * con = NULL;
main( argc, argv )
int argc;
char * argv[];
{
int fd;
struct stat statb;
while( --argc )
{
if( (*++argv)[0] == '-' )
switch( (*argv)[1] )
{
default:
fprintf( stderr, "invalid argument %s\n", *argv );
exit(1);
}
else
break;
}
if( argc == 0 )
{
more( NULL, fileno(stdin), 0L);
exit( 0 );
}
else
while( argc-- )
{
if( (fd = open( *argv, O_RDONLY+O_BINARY )) < 0 )
fprintf( stderr, "couldn't open %s\n", *argv );
else
{
statb.st_size = 0; /* just in case fstat fails */
fstat( fd, &statb );
more( *argv, fd, statb.st_size );
close( fd );
}
argv++;
if( argc )
{
printf( "%c[7m Next file: %s %c[0m", esc, *argv, esc );
chin();
printf( "\r%c[K", esc );
}
}
}
Local char buffer[BUFSIZ];
Local int bufp = 0;
Local long pos = 0;
Local int cnt = 0;
Local int eof;
initfile()
{
bufp = pos = cnt = 0;
eof = False;
}
long
getline( fd, line, linesize )
int fd;
char * line;
int linesize;
{
int linep;
bool eol;
if( eof )
return( -1 );
for( linep=0; linep < linesize; )
{
if( bufp >= cnt )
{
pos += cnt;
bufp = 0;
if( (cnt = read( fd, buffer, sizeof buffer )) == 0 )
{
if( linep != 0 )
{
eof = True;
break;
}
return( -1 );
}
}
/* newline signals eol */
if( buffer[bufp] == '\n' )
{
bufp++;
break;
}
else
if( buffer[bufp] == ctl_z )
{
eof = True;
break;
}
else
{
/* ignore crs */
if( buffer[bufp] != '\r' )
line[linep++] = buffer[bufp];
bufp++;
}
}
line[linep] = '\0';
return( pos + bufp );
}
more(fname, fd, size)
char * fname;
int fd;
long size;
{
int cnt;
char buf[80];
long pos;
long lineno = 0;
initfile();
if( fname )
{
printf( "%c[1m More: File <%s> %c[0m\n", esc, fname, esc );
cnt = 1;
}
else
cnt = 0;
while( (pos = getline( fd, buf, sizeof(buf)-1 )) >= 0 )
{
printf( "%s\n", buf );
lineno++;
if( (++cnt % 24) == 0 )
{
bool done;
if( size )
printf( "%c[7m -More(%ld%%)- %c[0m", esc,
((pos*100)/size), esc );
else
printf( "%c[7m -More- %c[0m", esc, esc );
for( done=False; !done; )
{
done = True;
switch( chin() )
{
case ' ':
cnt = 0;
break;
case '\r':
case '\n':
cnt--;
break;
case 'q':
printf( "\n" );
exit(0);
case 'v':
sprintf( buf, "v %s", fname );
system( buf );
cnt--;
break;
case ':':
switch( chin() )
{
case 'n':
printf( "\r%c[K", esc );
return;
}
default:
done = False;
break;
}
}
printf( "\r%c[K", esc );
}
}
}
/*
* !! Today's mystery: I have tried every way that I can think of
* to open con: in binary mode, using uSoft routines, and I just
* can't get it. I open with the right flags, using open or fopen,
* and the file descriptor comes up as non-binary when polled via
* ioctl. Even "setmode" doesn't work. What gives?
*
* the result is what follows:
*
*/
chin()
{
Local int confd = -1;
union REGS regs;
char far * buf; /* need -Ze to compile */
char buffer[1];
if( confd < 0 )
{
if( (confd = open("con", O_RDONLY)) < 0 )
{
fprintf( stderr, "couldn't open con:\n" );
exit(1);
}
/* get the current ioctl bits for con: */
regs.h.ah = 0x44;
regs.h.al = 0;
regs.x.bx = confd;
intdos( ®s, ®s );
/* flip on binary mode */
regs.h.ah = 0x44;
regs.h.al = 1;
regs.x.bx = confd;
regs.x.dx |= 0x20;
regs.x.dx &= ~(0x8010);
intdos( ®s, ®s );
}
/* read seems to be a bit problematical, also */
buf = buffer;
regs.h.ah = 0x3f;
regs.x.bx = confd;
/* !! small model - ds is the current ds */
regs.x.dx = FP_OFF(buf);
regs.x.cx = 1;
intdos( ®s, ®s );
return( buf[0] );
}
SHAR_EOF
cat << \SHAR_EOF > fgrep.c
#include "gen.h"
#include <stdio.h>
#include <fcntl.h>
Local char esc = '\033';
Local char ctl_z = '\032';
main( argc, argv )
int argc;
char * argv[];
{
FILE * fd;
int rc;
char * pattern;
while( --argc )
{
if( (*++argv)[0] == '-' )
switch( (*argv)[1] )
{
default:
fprintf( stderr, "invalid argument %s\n", *argv );
exit(1);
}
else
break;
}
if( argc == 0 )
{
fprintf( stderr, "usage: fgrep pattern [file ...]\n" );
exit(1);
}
pattern = *argv++;
argc--;
rc = 0;
if( argc == 0 )
{
rc = fgrep( NULL, pattern, stdin );
exit( 0 );
}
else
while( argc-- )
{
if( (fd = fopen( *argv, "r" )) == NULL )
fprintf( stderr, "couldn't open %s\n", *argv );
else
{
rc |= fgrep( *argv, pattern, fd );
close( fd );
}
argv++;
}
exit( !rc );
}
fgrep( file, pattern, fd )
char * file;
char * pattern;
FILE * fd;
{
char line[BUFSIZ];
int rc;
rc = 0;
while( fgets( line, sizeof(line), fd ) != NULL )
if( rc = match( pattern, line ) )
printf( "%s: %s", (file) ? file : "stdin", line );
return( rc );
}
match( pattern, line )
char * pattern;
char * line;
{
/* not a great algorithm */
char * ptr;
char * end;
int plen = strlen(pattern);
int llen = strlen(line);
if( plen > llen )
return( 0 );
end = line+(llen-plen);
for( ptr=line; ptr < end; ptr++ )
{
if( strncmp( pattern, ptr, plen ) == 0 )
return( 1 );
}
return( 0 );
}
SHAR_EOF
# End of shell archive
exit 0
More information about the Comp.sources.unix
mailing list