Added DIR (LS) command to list the files in a directory. This command is usable in Remote Console sessions.

This commit is contained in:
Mark Pizzolato 2013-04-23 12:39:03 -07:00
parent b04b7ae5b1
commit 9844ba6696
6 changed files with 303 additions and 16 deletions

View file

@ -21,7 +21,8 @@
### New Functionality
#### Remote Console Facility
A new capability has been added which allows a TELNET Connection to a user designated port so that some out of band commands can be entered to manipulate and/or adjust a running simulator. The commands which enable and control this capability are SET REMOTE TELNET=port, SET REMOTE CONNECTIONS=n and SHOW REMOTE.
A new capability has been added which allows a TELNET Connection to a user designated port so that some out of band commands can be entered to manipulate and/or adjust a running simulator. The commands which enable and control this capability are SET REMOTE TELNET=port, SET REMOTE CONNECTIONS=n, SET REMOTE TIMEOUT=seconds, and SHOW REMOTE.
A subset of normal simh commands are available for use in remote console sessions. These are: EXAMINE, IEXAMINE, DEPOSIT, EVALUATE, ATTACH, DETACH, ASSIGN, DEASSIGN, CONTINUE, PWD, SAVE, SET, SHOW, DIR, LS, ECHO, HELP
#### VAX/PDP11 Enhancements
RQ has new disk types: RC25, RCF25, RA80
@ -181,6 +182,8 @@ Other related changes/extensions:
SET DEFAULT Change working directory
PWD Show working directory
SHOW DEFAULT Show working directory
DIR {path|file} Display file listing
LS {path|file} Display file listing
#### Command Processing Enhancements

View file

@ -249,6 +249,13 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
endif
endif
endif
ifneq (,$(call find_include,glob))
OS_CCDEFS += -DHAVE_GLOB
else
ifneq (,$(call find_include,fnmatch))
OS_CCDEFS += -DHAVE_FNMATCH
endif
endif
ifneq (,$(NETWORK_USEFUL))
ifneq (,$(call find_include,pcap))
ifneq (,$(call find_lib,$(PCAPLIB)))

296
scp.c
View file

@ -647,6 +647,10 @@ static CTAB cmd_table[] = {
"cd set the current directory\n" },
{ "PWD", &pwd_cmd, 0,
"pwd show current directory\n" },
{ "DIR", &dir_cmd, 0,
"dir {dir} list directory files\n" },
{ "LS", &dir_cmd, 0,
"ls {dir} list directory files\n" },
{ "SET", &set_cmd, 0,
"set console arg{,arg...} set console options\n"
"set console WRU specify console drop to simh char\n"
@ -3147,6 +3151,251 @@ t_stat pwd_cmd (int32 flg, char *cptr)
return show_cmd (0, "DEFAULT");
}
#if defined (_WIN32)
t_stat dir_cmd (int flg, char *cptr)
{
HANDLE hFind;
WIN32_FIND_DATAA File;
struct stat filestat;
char WildName[PATH_MAX + 1];
if (*cptr == '\0')
cptr = "./*";
if ((!stat (cptr, &filestat)) && (filestat.st_mode & S_IFDIR)) {
sprintf (WildName, "%s%c*", cptr, strchr (cptr, '/') ? '/' : '\\');
cptr = WildName;
}
if ((hFind = FindFirstFileA (cptr, &File)) != INVALID_HANDLE_VALUE) {
t_int64 FileSize, TotalSize = 0;
int DirCount = 0, FileCount = 0;
char DirName[PATH_MAX + 1], FileName[PATH_MAX + 1];
char *c, pathsep = '/';
struct tm *local;
GetFullPathNameA(cptr, sizeof(DirName), DirName, &c);
c = strrchr(DirName, pathsep);
if (NULL == c) {
pathsep = '\\';
c = strrchr(cptr, pathsep);
}
if (c) {
memcpy(DirName, cptr, c - cptr);
DirName[c - cptr] = '\0';
}
else {
getcwd(DirName, PATH_MAX);
}
printf (" Directory of %s\n\n", DirName);
if (sim_log)
fprintf (sim_log, " Directory of %s\n\n", DirName);
do {
FileSize = (((t_int64)(File.nFileSizeHigh)) << 32) | File.nFileSizeLow;
sprintf (FileName, "%s%c%s", DirName, pathsep, File.cFileName);
stat (FileName, &filestat);
local = localtime (&filestat.st_mtime);
printf ("%02d/%02d/%04d %02d:%02d %s ", local->tm_mon+1, local->tm_mday, 1900+local->tm_year, local->tm_hour%12, local->tm_min, (local->tm_hour >= 12) ? "PM" : "AM");
if (sim_log)
fprintf (sim_log, "%02d/%02d/%04d %02d:%02d %s ", local->tm_mon+1, local->tm_mday, 1900+local->tm_year, local->tm_hour%12, local->tm_min, (local->tm_hour >= 12) ? "PM" : "AM");
if (filestat.st_mode & S_IFDIR) {
++DirCount;
printf (" <DIR> ");
if (sim_log)
fprintf (sim_log, " <DIR> ");
}
else {
if (filestat.st_mode & S_IFREG) {
++FileCount;
fprint_val (stdout, (t_value) FileSize, 10, 17, PV_RCOMMA);
if (sim_log)
fprint_val (sim_log, (t_value) FileSize, 10, 17, PV_RCOMMA);
TotalSize += FileSize;
}
else {
printf ("%17s", "");
if (sim_log)
fprintf (sim_log, "%17s", "");
}
}
printf (" %s\n", File.cFileName);
if (sim_log)
fprintf (sim_log, " %s\n", File.cFileName);
} while (FindNextFile (hFind, &File));
printf ("%16d File(s)", FileCount);
fprint_val (stdout, (t_value) TotalSize, 10, 15, PV_RCOMMA);
printf (" bytes\n");
printf ("%16d Dir(s)\n", DirCount);
if (sim_log) {
fprintf (sim_log, "%16d File(s)", FileCount);
fprint_val (sim_log, (t_value) TotalSize, 10, 15, PV_RCOMMA);
fprintf (sim_log, " bytes\n");
fprintf (sim_log, "%16d Dir(s)\n", DirCount);
}
FindClose (hFind);
}
else {
printf ("Can't list files for %s\n", cptr);
if (sim_log)
fprintf (sim_log, "Can't list files for %s\n", cptr);
return SCPE_ARG;
}
return SCPE_OK;
}
#else /* !defined (_WIN32) */
#if defined (HAVE_GLOB)
#include <glob.h>
#else /* !defined (HAVE_GLOB) */
#include <dirent.h>
#if defined (HAVE_FNMATCH)
#include <fnmatch.h>
#endif
#endif /* defined (HAVE_GLOB) */
t_stat dir_cmd (int flg, char *cptr)
{
#if defined (HAVE_GLOB)
glob_t paths;
#else
DIR *dir;
#endif
struct stat filestat;
char *c;
char DirName[PATH_MAX + 1], WholeName[PATH_MAX + 1], WildName[PATH_MAX + 1];
if (*cptr == '\0')
cptr = "./*";
strcpy (WildName, cptr);
while (strlen(WildName) && isspace(WildName[strlen(WildName)-1]))
WildName[strlen(WildName)-1] = '\0';
if ((!stat (WildName, &filestat)) && (filestat.st_mode & S_IFDIR)) {
strcat (WildName, "/*");
cptr = WildName;
}
if ((*cptr != '/') || (0 == memcmp (cptr, "./", 2)) || (0 == memcmp (cptr, "../", 3))) {
getcwd (WholeName, PATH_MAX);
strcat (WholeName, "/");
strcat (WholeName, cptr);
while (strlen(WholeName) && isspace(WholeName[strlen(WholeName)-1]))
WholeName[strlen(WholeName)-1] = '\0';
}
while ((c = strstr (WholeName, "/./")))
strcpy (c + 1, c + 3);
while ((c = strstr (WholeName, "//")))
strcpy (c + 1, c + 2);
while ((c = strstr (WholeName, "/../"))) {
char *c1;
c1 = c - 1;
while ((c1 >= WholeName) && (*c1 != '/'))
c1 = c1 - 1;
strcpy (c1, c + 3);
while (0 == memcmp (WholeName, "/../", 4))
strcpy (WholeName, WholeName+3);
}
c = strrchr (WholeName, '/');
if (c) {
memcpy (DirName, WholeName, c-WholeName);
DirName[c-WholeName] = '\0';
}
else
getcwd(DirName, PATH_MAX);
cptr = WholeName;
#if defined (HAVE_GLOB)
memset (&paths, 0, sizeof(paths));
if (0 == glob (cptr, 0, NULL, &paths)) {
#else
dir = opendir(DirName[0] ? DirName : "/.");
if (dir) {
struct dirent *ent;
#endif
t_int64 FileSize, TotalSize = 0;
int DirCount = 0, FileCount = 0;
char FileName[PATH_MAX + 1], *MatchName;
char *c;
struct tm *local;
int i;
MatchName = 1 + strrchr (cptr, '/');
printf (" Directory of %s\n\n", DirName[0] ? DirName : "/");
if (sim_log)
fprintf (sim_log, " Directory of %s\n\n", DirName[0] ? DirName : "/");
#if defined (HAVE_GLOB)
for (i=0; i<paths.gl_pathc; i++) {
sprintf (FileName, "%s", paths.gl_pathv[i]);
#else
while ((ent = readdir (dir))) {
#if defined (HAVE_FNMATCH)
if (fnmatch(MatchName, ent->d_name, 0))
continue;
#endif
sprintf (FileName, "%s/%s", DirName, ent->d_name);
#endif
stat (FileName, &filestat);
local = localtime (&filestat.st_mtime);
printf ("%02d/%02d/%04d %02d:%02d %s ", local->tm_mon+1, local->tm_mday, 1900+local->tm_year, local->tm_hour%12, local->tm_min, (local->tm_hour >= 12) ? "PM" : "AM");
if (sim_log)
fprintf (sim_log, "%02d/%02d/%04d %02d:%02d %s ", local->tm_mon+1, local->tm_mday, 1900+local->tm_year, local->tm_hour%12, local->tm_min, (local->tm_hour >= 12) ? "PM" : "AM");
if (filestat.st_mode & S_IFDIR) {
++DirCount;
printf (" <DIR> ");
if (sim_log)
fprintf (sim_log, " <DIR> ");
}
else {
if (filestat.st_mode & S_IFREG) {
++FileCount;
FileSize = filestat.st_size;
fprint_val (stdout, (t_value) FileSize, 10, 17, PV_RCOMMA);
if (sim_log)
fprint_val (sim_log, (t_value) FileSize, 10, 17, PV_RCOMMA);
TotalSize += FileSize;
}
else {
printf ("%17s", "");
if (sim_log)
fprintf (sim_log, "%17s", "");
}
}
c = strrchr (FileName, '/');
printf (" %s\n", c ? c + 1 : FileName);
if (sim_log)
fprintf (sim_log, " %s\n", c ? c + 1 : FileName);
}
if (FileCount) {
printf ("%16d File(s)", FileCount);
fprint_val (stdout, (t_value) TotalSize, 10, 15, PV_RCOMMA);
printf (" bytes\n");
printf ("%16d Dir(s)\n", DirCount);
if (sim_log) {
fprintf (sim_log, "%16d File(s)", FileCount);
fprint_val (sim_log, (t_value) TotalSize, 10, 15, PV_RCOMMA);
fprintf (sim_log, " bytes\n");
fprintf (sim_log, "%16d Dir(s)\n", DirCount);
}
}
else {
printf ("File Not Found\n");
if (sim_log)
fprintf (sim_log, "File Not Found\n");
}
#if defined (HAVE_GLOB)
globfree (&paths);
#else
closedir (dir);
#endif
}
else {
printf ("Can't list files for %s\n", cptr);
if (sim_log)
fprintf (sim_log, "Can't list files for %s\n", cptr);
return SCPE_ARG;
}
return SCPE_OK;
}
#endif /* !defined(_WIN32) */
/* Breakpoint commands */
t_stat brk_cmd (int32 flg, char *cptr)
@ -5804,9 +6053,9 @@ return val;
t_stat fprint_val (FILE *stream, t_value val, uint32 radix,
uint32 width, uint32 format)
{
#define MAX_WIDTH ((int) (CHAR_BIT * sizeof (t_value)))
#define MAX_WIDTH ((int) ((CHAR_BIT * sizeof (t_value) * 4 + 3)/3))
t_value owtest, wtest;
int32 d, digit, ndigits;
int32 d, digit, ndigits, commas = 0;
char dbuf[MAX_WIDTH + 1];
for (d = 0; d < MAX_WIDTH; d++)
@ -5820,16 +6069,39 @@ do {
dbuf[d] = (digit <= 9)? '0' + digit: 'A' + (digit - 10);
} while ((d > 0) && (val != 0));
if (format != PV_LEFT) {
wtest = owtest = radix;
ndigits = 1;
while ((wtest < width_mask[width]) && (wtest >= owtest)) {
owtest = wtest;
wtest = wtest * radix;
ndigits = ndigits + 1;
}
if ((MAX_WIDTH - ndigits) < d)
d = MAX_WIDTH - ndigits;
switch (format) {
case PV_LEFT:
break;
case PV_RCOMMA:
for (digit = 0; digit < MAX_WIDTH; digit++)
if (dbuf[digit] != ' ')
break;
ndigits = MAX_WIDTH - digit;
commas = (ndigits - 1)/3;
for (digit=0; digit<ndigits-3; digit++)
dbuf[MAX_WIDTH - ndigits + digit - (commas - (digit+1)/3)] = dbuf[MAX_WIDTH - ndigits + digit];
for (digit=1; digit<=commas; digit++)
dbuf[MAX_WIDTH - (digit * 4)] = ',';
d = d - commas;
if (width > MAX_WIDTH) {
fprintf (stream, "%*s", -((int)width), dbuf);
return SCPE_OK;
}
else
d = MAX_WIDTH - width;
break;
case PV_RZRO:
case PV_RSPC:
wtest = owtest = radix;
ndigits = 1;
while ((wtest < width_mask[width]) && (wtest >= owtest)) {
owtest = wtest;
wtest = wtest * radix;
ndigits = ndigits + 1;
}
if ((MAX_WIDTH - (ndigits + commas)) < d)
d = MAX_WIDTH - (ndigits + commas);
break;
}
if (fputs (&dbuf[d], stream) == EOF)
return SCPE_IOERR;

1
scp.h
View file

@ -71,6 +71,7 @@ t_stat set_cmd (int32 flag, char *ptr);
t_stat show_cmd (int32 flag, char *ptr);
t_stat set_default_cmd (int32 flg, char *cptr);
t_stat pwd_cmd (int32 flg, char *cptr);
t_stat dir_cmd (int32 flg, char *cptr);
t_stat brk_cmd (int32 flag, char *ptr);
t_stat do_cmd (int32 flag, char *ptr);
t_stat goto_cmd (int32 flag, char *ptr);

View file

@ -448,6 +448,8 @@ static CTAB allowed_remote_cmds[] = {
{ "SAVE", &save_cmd, 0 },
{ "SET", &set_cmd, 0 },
{ "SHOW", &show_cmd, 0 },
{ "DIR", &dir_cmd, 0 },
{ "LS", &dir_cmd, 0 },
{ "ECHO", &echo_cmd, 0 },
{ "HELP", &help_cmd, 0 },
{ NULL, NULL }
@ -586,10 +588,11 @@ for (i=0; i < sim_rem_con_tmxr.lines; i++) {
}
}
tmxr_send_buffered_data (lp); /* flush any buffered data */
printf ("Remote Console Command from %s> %s\n", lp->ipad, sim_rem_buf[i]);
printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]);
if (sim_log)
fprintf (sim_log, "Remote Console Command from %s> %s\n", lp->ipad, sim_rem_buf[i]);
if (strlen(sim_rem_buf[i]) >= sizeof(cbuf)) {
printf ("\r\nLine too long. Ignored. Continuing Simulator execution\r\n");
tmxr_linemsg (lp, "\r\nLine too long. Ignored. Continuing Simulator execution\r\n");
tmxr_send_buffered_data (lp); /* try to flush any buffered data */
break;
@ -627,7 +630,7 @@ for (i=0; i < sim_rem_con_tmxr.lines; i++) {
cmdp->message (NULL, stat); /* let it deal with display */
else
if (stat >= SCPE_BASE) { /* error? */
printf ("%s\n", sim_error_text (stat));
printf ("%s\r\n", sim_error_text (stat));
if (sim_log)
fprintf (sim_log, "%s\n", sim_error_text (stat));
}

View file

@ -285,7 +285,8 @@ typedef uint32 t_addr;
#define PV_RZRO 0 /* right, zero fill */
#define PV_RSPC 1 /* right, space fill */
#define PV_LEFT 2 /* left justify */
#define PV_RCOMMA 2 /* right, space fill. Comma separte every 3 */
#define PV_LEFT 3 /* left justify */
/* Default timing parameters */