Mail Archives: djgpp/1994/10/20/13:06:51
Dear Everyone,
It would really be good to have the unix utilities running on
MSDOS. Or it would even be better if had MSDOS utilities on
MSDOS that works like their UNIX counterpart, but which are
especially developed for MSDOS.
I personally was so in love with the UNIX style file
name globbing that I wrote an LS for DOS for myself, and I am
using it ever since. It is not a complete LS clone, so it has
only a tiny subset of its options ('l','a' and I created a 'd'
options to list only directori
es), and instead of the owner/
group/others set access modes it displays the MSDOS modes:
r/w/x/h/d/a, but you can say that 'ls -la [a-c]*doc' and it
works.
If anyone intrested, here is the code (I hope the comments
in it are good enough for documentation).
To compile it you need a C compiler, this file and the files
FNMATCH.C and FNMATCH.H from the GNU/DJGPP distribution.
(I also wrote a windows 'shell' for the most common DOS commands
that let me use the UNIX style globbing, so e.g. while ru
nning
WINDOWS I can type 'copy *a*doc b:' or 'del [^a]*exe' or simply
'dir *c'. If anyone is interested please contact me! As it uses
the WINIO Library from the book 'Undocumented Windows' I can only
send you the EXE file and my source, not the libraries you need
to compile it)
----------- CUT HERE ----------
/*==========================================================================*/
/* Name: LS.C (C) A. S˘lyom */
/* Task: LS a'la UNIX.
*/
/* To compile as a full program define the macro */
/* _USE_FNMATCH */
/* and compile it together with FNMATCH.C/FNMATCH.H from the GNU */
/* sources */
/* Example with Borland C++:
* bcc -D_USE_FNMATCH -I(where FNMATCH.H resides) ls.c fnmatch.c */
/* To use it as a function in one of your program define */
/* _FUNCTION_VERSION_ */
/* ------------- FREE PROGRAM USE AT YOUR OWN RI
SC ---------------- */
/* Date: 1994 Jan. 27. 09:24:43pm */
/* Changes: 07-29-94 11:08pm option -d to list only directories is added */
/*==========================================================================*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#ifdef __TURBOC__
#include <dos.h>
#endif
#ifdef _USE_FNMATCH
static char wildcard[128];
#include "fnmatch.h"
extern int
fnmatch(char *, char*, int);
#else
extern int CreateRanges(char *);
#endif
extern int IsFileNameMatched(char *);
struct _tagFtime {
unsigned ft_tsec:5; /* 0-29, double to get real seconds */
unsigned ft_min:6; /* 0-59 */
unsigned ft_hour:5; /* 0-23 */
};
struct _tagFdate {
unsigned ft_day:5; /* 1-31 */
unsigned ft_month:4; /* 1-12 */
unsigned ft_year:7; /* since 1980 */
};
typedef struct {
int attrib;
union {
struct _tagFti
me fTime;
unsigned nTime;
}ft;
union {
struct _tagFdate fDate;
unsigned nDate;
}fd;
long lSize;
char d_name[13];
}MYDIRENT;
static int isAll = 0; /* ls -a hidden files too */
static int isFull= 0; /* ls -l full names with flags */
static int onlyDirs= 0; /* ls -d only directories */
static int columns = 5;
static int numFiles = 0;
#define HIDFLAGS (FA_HIDDEN | FA_SYSTEM)
/*======================================================================*/
void Usage(char *pszProg)
/* TASK:
* EXPECTS:
* GLOBALS:
* RETURNS:
*/
/*----------------------------------------------------------------------*/
{
char *p;
p = strrchr(pszProg, '\\');
if(!p)
p = strrchr(pszProg, '/');
if(!p)
p = pszProg[1] == ':' ? pszProg+2 : pszProg;
else
++p;
if( strrchr(pszProg, '.') )
*strrchr(pszProg, '.') = 0;
printf("%s - UNIX like 'ls' with full regular expression filename match\n"
"(C) A. S˘lyom (1994)\n\n"
"Usage: %s [-flags] [path]\n"
" flags: a - list hidden files too\n"
" l - long list format\n"
" d - list only directories\n"
"
? - help\n"
" path: partial or full path to directory to be listed with optional\n"
" regular expression template for file names in that directory\n"
" The path must contain forward slashes (/) instead of the\n"
" backslashes (\\) found in DOS names, as the backslash is\n"
" reserved for regular expressions\n"
"Special
characters in filename expressions:\n"
" * any number of any character\n"
" ? any character\n"
" \\ escapes special meaning of * or ? or \\ \n"
" [] character groups (e.g. [ax.] or [1-9a-zA-Z]\n"
" [^] any character that is NOT in group. The '^' character\n"
" must be the first one in the square bracke
t\n"
"Examples: \n"
" %s -l *.[ch] List all \".c\" and \".h\" files in long format\n"
" %s -l *foo* List all file names containing \"foo\" (e.g. \"123foo.c\")\n"
" %s -a * List all hidden and normal files\n"
#if !defined(_FUNCTION_VERSION_)
"This program is FREEWARE ! Use it at your own risk!\n"
#endif
,p,p,p,p,p);
#if !defined(_FUNCTION_VERSION_)
exit(1);
#e
ndif
}
/*======================================================================*/
char *StripFileName(char *ps)
/* separate file name from path
* RETURNS: pointer to that file name of the path in 'ps'
* does not cut path
*/
/*----------------------------------------------------------------------*/
{
char *p;
p = strrchr(ps, '\\');
if(!p)
p = strrchr(ps, '/');
if(!p)
if(ps[1] == ':')
p =
ps+1;
if(p)
++p;
else
p = ps;
return p;
}
/*======================================================================*/
char *_SetupPath(char *s)
/*----------------------------------------------------------------------*/
{
char *p;
static char path[80];
int i;
strcpy(path, s);
for(p = s; *p; ++p)
if(*p == '\\' && *(p+1)!= '\\' && *(p+1)!= '?')
*p++ = '/'
;
p = StripFileName(s);
path[ p - s] = 0;
i = 0;
if( *p == '.' ) /* "dir .xx" */
{
i = 1;
wildcard[0] = '*';
}
strcpy( &wildcard[i], p);
if(!wildcard[0])
strcpy(wildcard, "*");
#ifndef _USE_FNMATCH
if(!CreateRanges(wildcard))
{
printf("Bad regular expression: '%s'\n", wildcard);
return NULL;
}
#
endif
strcat(path, "*.*");
return path;
}
#ifdef _USE_FNMATCH
/*======================================================================*/
int IsFileNameMatched(char *psz)
/*----------------------------------------------------------------------*/
{
//printf("DEBUG\n"
// " IsFileNameMatched-> string: '%s'. wildcard: '%s'\n", psz, wildcard);
return fnmatch(wildcard, psz, FNM_CASEFOLD) ? 0 : 1;
}
#endif
/*=============================================================
=========*/
void BadArgs(char *pszProg)
/* TASK:
* EXPECTS:
* GLOBALS:
* RETURNS:
*/
/*----------------------------------------------------------------------*/
{
printf("Invalid arguments !\n");
Usage(pszProg);
}
/*======================================================================*/
void GetOpts(char *pszProg, char *pszOpts)
/* TASK:
* EXPECTS:
* GLOBALS:
* RETURNS:
*/
/*----------------------------------------------------------------------*/
{
while(
*++pszOpts) /* skip '-' or to next flag */
{
switch(*pszOpts)
{
case 'a' :
isAll = 1;
break;
case 'l':
isFull = 1;
columns = 1;
break;
/* MOD 07-29-94 11:12pm 3 lines added */
case 'd':
on
lyDirs = 1;
break;
default:
BadArgs(pszProg);
break;
}
}
}
/*======================================================================*/
int CompFunc(const void *p1, const void *p2)
/* TASK: Perform directory name compare
* EXPECTS:
* GLOBALS:
* RETURNS:
*/
/*----------------------------------------------------------------------*/
{
return
strcmp( ( (MYDIRENT*)p1)->d_name, ( (MYDIRENT*)p2)->d_name);
}
/*======================================================================*/
#ifdef _FUNCTION_VERSION_
int ls(int argc, char **argv)
#else
int main(int argc, char **argv)
#endif
/* TASK: Perform directory listing
* EXPECTS:
* GLOBALS:
* RETURNS: main() returns 1 if error, 0 otherwise, ls() returns 0 if error,
* 1 otherwise
*/
/*----------------------------------------------------------------------*/
{
DIR *pdir;
struct dirent *pd;
MYDIRENT *pdeFiles=NULL, *pTmp;
char szPath[128];
char szName[64];
char *p;
int i = 1;
long lSum = 0;
#ifdef _USE_FNMATCH
extern char *_SetupPath(char *s);
#endif
#ifdef _FUNCTION_VERSION_
isAll = 0; /* ls -a hidden files too */
isFull= 0; /* ls -l full names with flags */
/* MOD 07-29-94 11:23pm 1 line added */
onlyDirs = 0; /* ls -d list directories only */
columns = 5;
numFiles = 0;
#endif
if(argc == 1)
strcpy(szPath,"*");
else if(argc > 3)
BadArgs(argv[0]);
else if(argc == 3 && argv[1][0] != '-' && argv[1][0] != '/')
BadArgs(argv[0]);
else if (argc == 2 &&
(argv[1][0] == '?' || (argv[1][0] == '-
' && argv[1][0] == '?')) )
{
Usage(argv[0]);
#ifdef _FUNCTION_VERSION_
return 1;
#endif
}
else
{
if(argc > 1 && argv[1][0] == '-')
{
GetOpts(argv[0], argv[1]);
i = 2;
}
if(argc > i)
strcpy(szPath, argv[i]);
else
strcpy(szPath,"*");
}
p
= strrchr(szPath, '/');
if(!p)
p = strrchr(szPath, '\\');
if(p)
++p;
else if(szPath[1] == ':')
p = &szPath[2];
else
p = szPath;
strcpy(szName, p);
*p = 0;
for(p = szPath; *p; p++)
if(*p == '/')
*p = '\\';
if(!szName[0])
strcpy(szName, "*");
#ifdef _USE_FNMATCH
_SetupPath(szName); /
* see SH.C */
#else
if(!CreateRanges(szName))
{
printf("ls - Bad regular expression: '%s'\n", szName);
#ifdef _FUNCTION_VERSION_
return 0;
#else
exit(1);
#endif
}
#endif
/* _USE_FNMATCH */
if(!szPath[0])
strcpy(szPath, ".\\");
pdir = opendir(szPath);
if(!pdir)
{
printf("Directory '%s' does not exist\n");
#ifdef _FUNCTION_VERSION_
return 0;
#else
exit(1);
#endif
}
while( (pd = readdir(pdir)) != NULL)
{
#ifdef __TURBOC__
if( ( ( ((struct find_t *)pdir)->attrib & FA_LABEL) != 0)
||
(
!isAll &&
(
( (( (struct find_t *)pdir)->attrib & HIDFLAGS) != 0) ||
pd->d
_name[0] == '.'
)
/* MOD 07-29-94 11:19pm 5 lines added */
||
(
onlyDirs
&&
(( (struct find_t *)pdir)->attrib & FA_DIREC) == 0
)
)
)
continue;
#endif
if( IsFileNameMatched(pd->d_name) )
{
pTmp = pdeFiles;
if(!pdeFiles)
pTmp = malloc(sizeof(MYDIRENT));
else
pTmp = realloc(pdeFiles,
(numFiles + 1) * sizeof(MYDIRENT));
if(pTmp)
pdeFil
es = pTmp;
else
{
printf("***** Out of memory...\n");
if(pdeFiles)
{
printf("Files found so far:\n\n");
break; /* out of while */
}
else
{
closedir(pdir);
#ifdef _FUNCTION_VERSION_
return 0;
#else
exit(1);
#endif
}
}
strcpy( (pdeFiles + numFiles)->d_name, pd->d_name);
(pdeFiles + numFiles)->attrib = ( (struct find_t *)pdir)->attrib;
(pdeFiles + numFiles)->fd.nDate =
( (struct find_t *)pdir)->wr_date;
(pdeFiles + numFiles)->ft.nTime =
( (struct find_t *)pdir)->wr_time;
/* MOD 08-02-94 07:43pm 1 line
* (pdeFiles + numFiles++)->lSize = ( (struct find_t *)pdir)->size;
*/
lSum += (pdeFiles + numFiles++)->lSize = ( (struct find_t *)pdir)->size;
}
}
/* while */
closedir(pdir);
if(numFiles)
{
int i,j;
char *p;
qsort( (void *) pdeFiles, numFiles, sizeof(MYDIRENT), CompFunc);
pTmp = pdeFiles;
/* MOD 08-02-94 07:45pm 2 lines added */
if(lSum && isFull)
printf("total: %ld\n", lSum);
for( i = 0; i < numFiles; i += columns)
{
for(j =
0; j < columns && (j+i) < numFiles; j++)
{
if( (pTmp->attrib & FA_DIREC) == 0 )
strlwr(pTmp->d_name);
if(isFull)
{
if(pTmp->attrib & FA_DIREC)
fputchar('d');
else
fputchar('-');
fputchar('r'); /* all DOS file can be read */
if(pTmp->attrib & FA_RDONLY)
fputchar('-');
else
fputchar('w');
p = strchr(pTmp->d_name, '.');
if(p)
{
++p;
if(strcmp(p, "com") == 0 || stricmp(p, "exe") == 0 ||
stricmp(p, "bat") == 0)
{
fputchar('x');
}
else
fputchar('-');
}
else if(pTmp->attrib & FA_DIREC)
fputchar('x');
else
fputchar('-');
if(pTmp->attrib & FA_HIDDEN)
fputchar('h');
else
fputchar('-');
if(pTmp->attrib & FA_SYSTEM)
fputchar('s');
else
fputchar('-');
if(pTmp->attrib & FA_ARCH)
fputchar('a');
else
fputchar('-');
printf("\ %7lu %02d-%02d-%02d %02d:%02d \t%-15s",
pTmp->lSize,
pTmp->fd.fDate.ft_month,
pTmp->fd.fDate.ft_day,
pTmp->fd.fDate.ft_year+80,
pTmp->ft.fTime.ft_hour,
pTmp->ft.fTime.ft_min,
pTmp->d_name);
}
else
{
printf("%-15s", pTmp->d_name);
}
++pTmp;
}
printf("\n");
}
free(pdeFiles);
}
#ifdef _FUNCTION_VERSION_
return 1;
#else
return 0;
#endif
}
----------- CUT HERE ----------
Adras Solyom
- Raw text -