diff --git a/scp.c b/scp.c
index ed5e67ee..0a8c367b 100644
--- a/scp.c
+++ b/scp.c
@@ -4986,28 +4986,30 @@ t_stat pwd_cmd (int32 flg, CONST char *cptr)
return show_cmd (0, "DEFAULT");
}
+typedef void (*DIR_ENTRY_CALLBACK)(const char *directory,
+ const char *filename,
+ t_offset FileSize,
+ const struct stat *filestat,
+ void *context);
+
#if defined (_WIN32)
-t_stat dir_cmd (int32 flg, CONST char *cptr)
+static t_stat sim_dir_scan (const char *cptr, DIR_ENTRY_CALLBACK entry, void *context)
{
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;
+ t_int64 FileSize;
char DirName[PATH_MAX + 1], FileName[PATH_MAX + 1];
const char *c;
char pathsep = '/';
- struct tm *local;
GetFullPathNameA(cptr, sizeof(DirName), DirName, (char **)&c);
c = strrchr(DirName, pathsep);
@@ -5022,39 +5024,17 @@ if ((hFind = FindFirstFileA (cptr, &File)) != INVALID_HANDLE_VALUE) {
else {
getcwd(DirName, PATH_MAX);
}
- sim_printf (" Directory of %s\n\n", DirName);
+ sprintf (&DirName[strlen (DirName)], "%c", pathsep);
do {
FileSize = (((t_int64)(File.nFileSizeHigh)) << 32) | File.nFileSizeLow;
- sprintf (FileName, "%s%c%s", DirName, pathsep, File.cFileName);
+ sprintf (FileName, "%s%s", DirName, File.cFileName);
stat (FileName, &filestat);
- local = localtime (&filestat.st_mtime);
- sim_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 (filestat.st_mode & S_IFDIR) {
- ++DirCount;
- sim_printf ("
");
- }
- else {
- if (filestat.st_mode & S_IFREG) {
- ++FileCount;
- sim_print_val ((t_value) FileSize, 10, 17, PV_RCOMMA);
- TotalSize += FileSize;
- }
- else {
- sim_printf ("%17s", "");
- }
- }
- sim_printf (" %s\n", File.cFileName);
+ entry (DirName, File.cFileName, FileSize, &filestat, context);
} while (FindNextFile (hFind, &File));
- sim_printf ("%16d File(s)", FileCount);
- sim_print_val ((t_value) TotalSize, 10, 15, PV_RCOMMA);
- sim_printf (" bytes\n");
- sim_printf ("%16d Dir(s)\n", DirCount);
FindClose (hFind);
}
-else {
- sim_printf ("Can't list files for %s\n", cptr);
+else
return SCPE_ARG;
- }
return SCPE_OK;
}
@@ -5069,7 +5049,7 @@ return SCPE_OK;
#endif
#endif /* defined (HAVE_GLOB) */
-t_stat dir_cmd (int32 flg, CONST char *cptr)
+static t_stat sim_dir_scan (const char *cptr, DIR_ENTRY_CALLBACK entry, void *context)
{
#if defined (HAVE_GLOB)
glob_t paths;
@@ -5080,13 +5060,9 @@ struct stat filestat;
char *c;
char DirName[PATH_MAX + 1], WholeName[PATH_MAX + 1], WildName[PATH_MAX + 1];
-if (*cptr == '\0')
- strcpy (WildName, "./*");
-else
- strcpy (WildName, cptr);
+strcpy (WildName, cptr);
cptr = WildName;
-while (strlen(WildName) && sim_isspace(WildName[strlen(WildName)-1]))
- WildName[strlen(WildName)-1] = '\0';
+sim_trim_endspc (WildName);
if ((!stat (WildName, &filestat)) && (filestat.st_mode & S_IFDIR))
strcat (WildName, "/*");
if ((*cptr != '/') || (0 == memcmp (cptr, "./", 2)) || (0 == memcmp (cptr, "../", 3))) {
@@ -5097,8 +5073,7 @@ if ((*cptr != '/') || (0 == memcmp (cptr, "./", 2)) || (0 == memcmp (cptr, "../"
#endif
strcat (WholeName, "/");
strcat (WholeName, cptr);
- while (strlen(WholeName) && sim_isspace(WholeName[strlen(WholeName)-1]))
- WholeName[strlen(WholeName)-1] = '\0';
+ sim_trim_endspc (WholeName);
}
while ((c = strstr (WholeName, "/./")))
strcpy (c + 1, c + 3);
@@ -5133,19 +5108,17 @@ dir = opendir(DirName[0] ? DirName : "/.");
if (dir) {
struct dirent *ent;
#endif
- t_offset FileSize, TotalSize = 0;
- int DirCount = 0, FileCount = 0;
+ t_offset FileSize;
char FileName[PATH_MAX + 1];
#if defined (HAVE_FNMATCH)
char *MatchName = 1 + strrchr (cptr, '/');;
#endif
- char *c;
+ char *p_name;
struct tm *local;
#if defined (HAVE_GLOB)
size_t i;
#endif
- sim_printf (" Directory of %s\n\n", DirName[0] ? DirName : "/");
#if defined (HAVE_GLOB)
for (i=0; id_name);
#endif
+ p_name = FileName + strlen (DirName);
stat (FileName, &filestat);
- local = localtime (&filestat.st_mtime);
- sim_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 (filestat.st_mode & S_IFDIR) {
- ++DirCount;
- sim_printf (" ");
- }
- else {
- if (filestat.st_mode & S_IFREG) {
- ++FileCount;
- FileSize = sim_fsize_name_ex (FileName);
- sim_print_val ((t_value) FileSize, 10, 17, PV_RCOMMA);
- TotalSize += FileSize;
- }
- else {
- sim_printf ("%17s", "");
- }
- }
- c = strrchr (FileName, '/');
- sim_printf (" %s\n", c ? c + 1 : FileName);
- }
- if (FileCount) {
- sim_printf ("%16d File(s)", FileCount);
- sim_print_val ((t_value) TotalSize, 10, 15, PV_RCOMMA);
- sim_printf (" bytes\n");
- sim_printf ("%16d Dir(s)\n", DirCount);
- }
- else {
- sim_printf ("File Not Found\n");
+ FileSize = (t_offset)((filestat.st_mode & S_IFDIR) ? 0 : sim_fsize_name_ex (FileName));
+ entry (DirName, p_name, FileSize, &filestat, context);
}
#if defined (HAVE_GLOB)
globfree (&paths);
@@ -5193,15 +5141,120 @@ if (dir) {
closedir (dir);
#endif
}
-else {
- sim_printf ("Can't list files for %s\n", cptr);
+else
return SCPE_ARG;
- }
return SCPE_OK;
}
-
#endif /* !defined(_WIN32) */
+typedef struct {
+ char LastDir[PATH_MAX + 1];
+ t_offset TotalBytes;
+ int TotalDirs;
+ int TotalFiles;
+ int DirChanges;
+ int DirCount;
+ int FileCount;
+ t_offset ByteCount;
+ } DIR_CTX;
+
+static void sim_dir_entry (const char *directory,
+ const char *filename,
+ t_offset FileSize,
+ const struct stat *filestat,
+ void *context)
+{
+DIR_CTX *ctx = (DIR_CTX *)context;
+struct tm *local;
+
+if ((directory == NULL) || (filename == NULL)) {
+ if (ctx->DirChanges > 1)
+ sim_printf (" Total Files Listed:\n");
+ if (ctx->DirChanges > 0) {
+ sim_printf ("%16d File(s) ", ctx->TotalFiles);
+ sim_print_val ((t_value) ctx->TotalBytes, 10, 17, PV_RCOMMA);
+ sim_printf (" bytes\n");
+ sim_printf ("%16d Dir(s)\n", ctx->TotalDirs);
+ }
+ return;
+ }
+if (strcmp (ctx->LastDir, directory)) {
+ if (ctx->DirCount || ctx->FileCount) {
+ sim_printf ("%16d File(s) ", ctx->FileCount);
+ sim_print_val ((t_value) ctx->ByteCount, 10, 17, PV_RCOMMA);
+ sim_printf (" bytes\n");
+ ctx->ByteCount = ctx->DirCount = ctx->FileCount = 0;
+ sim_printf ("%16d Dir(s)\n", ctx->DirCount);
+ }
+ ++ctx->DirChanges;
+ sim_printf (" Directory of %*.*s\n\n", strlen (directory) - 1, strlen (directory) - 1, directory);
+ strcpy (ctx->LastDir, directory);
+ }
+local = localtime (&filestat->st_mtime);
+sim_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 (filestat->st_mode & S_IFDIR) {
+ ++ctx->DirCount;
+ ++ctx->TotalDirs;
+ sim_printf (" ");
+ }
+else {
+ if (filestat->st_mode & S_IFREG) {
+ ++ctx->FileCount;
+ ++ctx->TotalFiles;
+ sim_print_val ((t_value) FileSize, 10, 17, PV_RCOMMA);
+ ctx->ByteCount += FileSize;
+ ctx->TotalBytes += FileSize;
+ }
+ else {
+ sim_printf ("%17s", "");
+ }
+ }
+sim_printf (" %s\n", filename);
+}
+
+t_stat dir_cmd (int32 flg, CONST char *cptr)
+{
+DIR_CTX dir_state;
+t_stat stat;
+
+memset (&dir_state, 0, sizeof (dir_state));
+if (*cptr == '\0')
+ cptr = "./*";
+stat = sim_dir_scan (cptr, sim_dir_entry, &dir_state);
+sim_dir_entry (NULL, NULL, 0, NULL, &dir_state); /* output summary */
+if (stat != SCPE_OK)
+ return sim_messagef (SCPE_ARG, "File Not Found\n");
+return stat;
+}
+
+
+typedef struct {
+ t_stat stat;
+ } TYPE_CTX;
+
+static void sim_type_entry (const char *directory,
+ const char *filename,
+ t_offset FileSize,
+ const struct stat *filestat,
+ void *context)
+{
+TYPE_CTX *ctx = (TYPE_CTX *)context;
+char FullPath[PATH_MAX + 1];
+FILE *file;
+char lbuf[4*CBUFSIZE];
+
+sprintf (FullPath, "%s%s", directory, filename);
+
+file = sim_fopen (FullPath, "r");
+if (file == NULL) /* open failed? */
+ return;
+sim_printf ("\n%s\n\n", FullPath);
+lbuf[sizeof(lbuf)-1] = '\0';
+while (fgets (lbuf, sizeof(lbuf)-1, file))
+ sim_printf ("%s", lbuf);
+fclose (file);
+}
+
t_stat type_cmd (int32 flg, CONST char *cptr)
{
@@ -5214,8 +5267,16 @@ lbuf[sizeof(lbuf)-1] = '\0';
strncpy (lbuf, cptr, sizeof(lbuf)-1);
sim_trim_endspc(lbuf);
file = sim_fopen (lbuf, "r");
-if (file == NULL) /* open failed? */
- return SCPE_OPENERR;
+if (file == NULL) { /* open failed? */
+ TYPE_CTX type_state;
+ t_stat stat;
+
+ memset (&type_state, 0, sizeof (type_state));
+ stat = sim_dir_scan (cptr, sim_type_entry, &type_state);
+ if (stat == SCPE_OK)
+ return SCPE_OK;
+ return sim_messagef (SCPE_OPENERR, "The system cannot find the file specified.\n");
+ }
lbuf[sizeof(lbuf)-1] = '\0';
while (fgets (lbuf, sizeof(lbuf)-1, file))
sim_printf ("%s", lbuf);
@@ -5223,18 +5284,38 @@ fclose (file);
return SCPE_OK;
}
+typedef struct {
+ t_stat stat;
+ } DEL_CTX;
+
+static void sim_delete_entry (const char *directory,
+ const char *filename,
+ t_offset FileSize,
+ const struct stat *filestat,
+ void *context)
+{
+DEL_CTX *ctx = (DEL_CTX *)context;
+char FullPath[PATH_MAX + 1];
+
+sprintf (FullPath, "%s%s", directory, filename);
+
+if (!unlink (FullPath))
+ return;
+ctx->stat = sim_messagef (SCPE_ARG, "%s\n", strerror (errno));
+}
+
t_stat delete_cmd (int32 flg, CONST char *cptr)
{
-char lbuf[4*CBUFSIZE];
+DEL_CTX del_state;
+t_stat stat;
if ((!cptr) || (*cptr == 0))
return SCPE_2FARG;
-lbuf[sizeof(lbuf)-1] = '\0';
-strncpy (lbuf, cptr, sizeof(lbuf)-1);
-sim_trim_endspc(lbuf);
-if (!unlink (lbuf))
- return SCPE_OK;
-return sim_messagef (SCPE_ARG, "%s\n", strerror (errno));
+memset (&del_state, 0, sizeof (del_state));
+stat = sim_dir_scan (cptr, sim_delete_entry, &del_state);
+if (stat == SCPE_OK)
+ return del_state.stat;
+return sim_messagef (SCPE_ARG, "No such file or directory: %s\n", cptr);
}
/* Breakpoint commands */