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( &regs, &regs );

		/* 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( &regs, &regs );

		}

	/*  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( &regs, &regs );

	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