mirror of
https://github.com/rcornwell/sims.git
synced 2026-05-04 07:00:17 +00:00
SCP: Update to current version
This commit is contained in:
216
scp.c
216
scp.c
@@ -1029,16 +1029,24 @@ static const char simh_help[] =
|
||||
"2Displaying Files\n"
|
||||
#define HLP_TYPE "*Commands Displaying_Files TYPE"
|
||||
"3TYPE\n"
|
||||
"++TYPE {file} display a file contents\n"
|
||||
"++TYPE file display a file contents\n"
|
||||
#define HLP_CAT "*Commands Displaying_Files CAT"
|
||||
"3CAT\n"
|
||||
"++CAT {file} display a file contents\n"
|
||||
"++CAT file display a file contents\n"
|
||||
"2Removing Files\n"
|
||||
#define HLP_DELETE "*Commands Removing_Files DEL"
|
||||
"3DELETE\n"
|
||||
"++DEL{ete} {file} deletes a file\n"
|
||||
"++DEL{ete} file deletes a file\n"
|
||||
#define HLP_RM "*Commands Removing_Files RM"
|
||||
"3RM\n"
|
||||
"++RM {file} deletes a file\n"
|
||||
"++RM file deletes a file\n"
|
||||
"2Copying Files\n"
|
||||
#define HLP_COPY "*Commands Copying_Files COPY"
|
||||
"3COPY\n"
|
||||
"++COPY sfile dfile copies a file\n"
|
||||
#define HLP_CP "*Commands Copying_Files CP"
|
||||
"3CP\n"
|
||||
"++CP sfile dfile copies a file\n"
|
||||
#define HLP_SET "*Commands SET"
|
||||
"2SET\n"
|
||||
/***************** 80 character line width template *************************/
|
||||
@@ -1839,6 +1847,8 @@ static CTAB cmd_table[] = {
|
||||
{ "CAT", &type_cmd, 0, HLP_CAT },
|
||||
{ "DELETE", &delete_cmd, 0, HLP_DELETE },
|
||||
{ "RM", &delete_cmd, 0, HLP_RM },
|
||||
{ "COPY", ©_cmd, 0, HLP_COPY },
|
||||
{ "CP", ©_cmd, 0, HLP_CP },
|
||||
{ "SET", &set_cmd, 0, HLP_SET },
|
||||
{ "SHOW", &show_cmd, 0, HLP_SHOW },
|
||||
{ "DO", &do_cmd, 1, HLP_DO },
|
||||
@@ -2027,7 +2037,7 @@ for (i = 1; i < argc; i++) { /* loop thru args */
|
||||
return 0;
|
||||
}
|
||||
if (*cbuf) /* concat args */
|
||||
strcat (cbuf, " ");
|
||||
sim_strlcat (cbuf, " ", sizeof(cbuf));
|
||||
sprintf(&cbuf[strlen(cbuf)], "%s%s%s", strchr(argv[i], ' ') ? "\"" : "", argv[i], strchr(argv[i], ' ') ? "\"" : "");
|
||||
lookswitch = FALSE; /* no more switches */
|
||||
}
|
||||
@@ -2113,7 +2123,7 @@ else if (*argv[0]) { /* sim name arg? */
|
||||
strncpy (nbuf + 1, argv[0], PATH_MAX + 1); /* copy sim name */
|
||||
if ((np = (char *)match_ext (nbuf, "EXE"))) /* remove .exe */
|
||||
*np = 0;
|
||||
strcat (nbuf, ".ini\""); /* add .ini" */
|
||||
strlcat (nbuf, ".ini\"", sizeof(nbuf)); /* add .ini" */
|
||||
stat = do_cmd (-1, nbuf) & ~SCPE_NOMESSAGE; /* proc default cmd file */
|
||||
if (stat == SCPE_OPENERR) { /* didn't exist/can't open? */
|
||||
np = strrchr (nbuf, '/'); /* stript path and try again in cwd */
|
||||
@@ -2906,7 +2916,8 @@ for (nargs = 0; nargs < 10; ) { /* extract arguments */
|
||||
if (do_arg [0] == NULL) /* need at least 1 */
|
||||
return SCPE_2FARG;
|
||||
if ((fpin = fopen (do_arg[0], "r")) == NULL) { /* file failed to open? */
|
||||
strcat (strcpy (cbuf, do_arg[0]), ".sim"); /* try again with .sim extension */
|
||||
strlcpy (cbuf, do_arg[0], sizeof (cbuf)); /* try again with .sim extension */
|
||||
strlcat (cbuf, ".sim", sizeof (cbuf));
|
||||
if ((fpin = fopen (cbuf, "r")) == NULL) { /* failed a second time? */
|
||||
if (flag == 0) /* cmd line file? */
|
||||
fprintf (stderr, "Can't open file %s\n", do_arg[0]);
|
||||
@@ -2937,7 +2948,8 @@ if (flag >= 0) { /* Only bump nesting fro
|
||||
}
|
||||
}
|
||||
|
||||
strcpy( sim_do_filename[sim_do_depth], do_arg[0]); /* stash away do file name for possible use by 'call' command */
|
||||
sim_strlcpy( sim_do_filename[sim_do_depth], do_arg[0],
|
||||
sizeof (sim_do_filename[sim_do_depth])); /* stash away do file name for possible use by 'call' command */
|
||||
sim_do_label[sim_do_depth] = label; /* stash away do label for possible use in messages */
|
||||
sim_goto_line[sim_do_depth] = 0;
|
||||
if (label) {
|
||||
@@ -3738,8 +3750,11 @@ int32 saved_goto_line = sim_goto_line[sim_do_depth];
|
||||
|
||||
if (NULL == sim_gotofile) return SCPE_UNK; /* only valid inside of do_cmd */
|
||||
get_glyph (fcptr, gbuf1, 0);
|
||||
if ('\0' == gbuf1[0]) return SCPE_ARG; /* unspecified goto target */
|
||||
if ('\0' == gbuf1[0]) /* unspecified goto target */
|
||||
return sim_messagef (SCPE_ARG, "Missing goto target\n");
|
||||
fpos = ftell(sim_gotofile); /* Save start position */
|
||||
if (fpos < 0)
|
||||
return sim_messagef (SCPE_IERR, "goto ftell error: %s\n", strerror (errno));
|
||||
rewind(sim_gotofile); /* start search for label */
|
||||
sim_goto_line[sim_do_depth] = 0; /* reset line number */
|
||||
sim_do_echo = 0; /* Don't echo while searching for label */
|
||||
@@ -3751,7 +3766,7 @@ while (1) {
|
||||
if (*cptr != ':') continue; /* ignore non-labels */
|
||||
++cptr; /* skip : */
|
||||
while (sim_isspace (*cptr)) ++cptr; /* skip blanks */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get label glyph */
|
||||
get_glyph (cptr, gbuf, 0); /* get label glyph */
|
||||
if (0 == strcmp(gbuf, gbuf1)) {
|
||||
sim_brk_clract (); /* goto defangs current actions */
|
||||
sim_do_echo = saved_do_echo; /* restore echo mode */
|
||||
@@ -3761,9 +3776,10 @@ while (1) {
|
||||
}
|
||||
}
|
||||
sim_do_echo = saved_do_echo; /* restore echo mode */
|
||||
fseek(sim_gotofile, fpos, SEEK_SET); /* restore start position */
|
||||
sim_goto_line[sim_do_depth] = saved_goto_line; /* restore start line number */
|
||||
return SCPE_ARG;
|
||||
if (fseek(sim_gotofile, fpos, SEEK_SET)) /* restore start position */
|
||||
return sim_messagef (SCPE_IERR, "goto seek error: %s\n", strerror (errno));
|
||||
return sim_messagef (SCPE_ARG, "goto target '%s' not found\n", gbuf1);
|
||||
}
|
||||
|
||||
/* Return command */
|
||||
@@ -5072,23 +5088,25 @@ struct stat filestat;
|
||||
char *c;
|
||||
char DirName[PATH_MAX + 1], WholeName[PATH_MAX + 1], WildName[PATH_MAX + 1];
|
||||
|
||||
strcpy (WildName, cptr);
|
||||
memset (DirName, 0, sizeof(DirName));
|
||||
memset (WholeName, 0, sizeof(WholeName));
|
||||
sim_strlcpy (WildName, cptr, sizeof(WildName));
|
||||
cptr = WildName;
|
||||
sim_trim_endspc (WildName);
|
||||
if ((!stat (WildName, &filestat)) && (filestat.st_mode & S_IFDIR))
|
||||
strcat (WildName, "/*");
|
||||
strlcat (WildName, "/*", sizeof(WildName));
|
||||
if ((*cptr != '/') || (0 == memcmp (cptr, "./", 2)) || (0 == memcmp (cptr, "../", 3))) {
|
||||
#if defined (VMS)
|
||||
getcwd (WholeName, PATH_MAX, 0);
|
||||
getcwd (WholeName, sizeof(WholeName)-1, 0);
|
||||
#else
|
||||
getcwd (WholeName, PATH_MAX);
|
||||
getcwd (WholeName, sizeof(WholeName)-1);
|
||||
#endif
|
||||
strcat (WholeName, "/");
|
||||
strcat (WholeName, cptr);
|
||||
strlcat (WholeName, "/", sizeof(WholeName));
|
||||
strlcat (WholeName, cptr, sizeof(WholeName));
|
||||
sim_trim_endspc (WholeName);
|
||||
}
|
||||
else
|
||||
strcpy (WholeName, cptr);
|
||||
sim_strlcpy (WholeName, cptr, sizeof(WholeName));
|
||||
while ((c = strstr (WholeName, "/./")))
|
||||
memmove (c + 1, c + 3, 1 + strlen (c + 3));
|
||||
while ((c = strstr (WholeName, "//")))
|
||||
@@ -5109,9 +5127,9 @@ if (c) {
|
||||
}
|
||||
else {
|
||||
#if defined (VMS)
|
||||
getcwd (WholeName, PATH_MAX, 0);
|
||||
getcwd (WholeName, sizeof(WholeName)-1, 0);
|
||||
#else
|
||||
getcwd (WholeName, PATH_MAX);
|
||||
getcwd (WholeName, sizeof(WholeName)-1);
|
||||
#endif
|
||||
}
|
||||
cptr = WholeName;
|
||||
@@ -5146,7 +5164,8 @@ if (dir) {
|
||||
sprintf (FileName, "%s/%s", DirName, ent->d_name);
|
||||
#endif
|
||||
p_name = FileName + strlen (DirName);
|
||||
stat (FileName, &filestat);
|
||||
memset (&filestat, 0, sizeof (filestat));
|
||||
(void)stat (FileName, &filestat);
|
||||
FileSize = (t_offset)((filestat.st_mode & S_IFDIR) ? 0 : sim_fsize_name_ex (FileName));
|
||||
entry (DirName, p_name, FileSize, &filestat, context);
|
||||
}
|
||||
@@ -5333,6 +5352,62 @@ if (stat == SCPE_OK)
|
||||
return sim_messagef (SCPE_ARG, "No such file or directory: %s\n", cptr);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
t_stat stat;
|
||||
int count;
|
||||
char destname[CBUFSIZE];
|
||||
} COPY_CTX;
|
||||
|
||||
static void sim_copy_entry (const char *directory,
|
||||
const char *filename,
|
||||
t_offset FileSize,
|
||||
const struct stat *filestat,
|
||||
void *context)
|
||||
{
|
||||
COPY_CTX *ctx = (COPY_CTX *)context;
|
||||
struct stat deststat;
|
||||
char FullPath[PATH_MAX + 1];
|
||||
char dname[CBUFSIZE];\
|
||||
t_stat st;
|
||||
|
||||
sim_strlcpy (dname, ctx->destname, sizeof (dname));
|
||||
|
||||
sprintf (FullPath, "%s%s", directory, filename);
|
||||
|
||||
if ((dname[strlen (dname) - 1] == '/') || (dname[strlen (dname) - 1] == '\\'))
|
||||
dname[strlen (dname) - 1] = '\0';
|
||||
if ((!stat (dname, &deststat)) && (deststat.st_mode & S_IFDIR)) {
|
||||
const char *dslash = (strrchr (dname, '/') ? "/" : (strrchr (dname, '\\') ? "\\" : "/"));
|
||||
|
||||
dname[sizeof (dname) - 1] = '\0';
|
||||
snprintf (&dname[strlen (dname)], sizeof (dname) - strlen (dname), "%s%s", dslash, filename);
|
||||
}
|
||||
st = sim_copyfile (FullPath, dname, TRUE);
|
||||
if (SCPE_OK == st)
|
||||
++ctx->count;
|
||||
else
|
||||
ctx->stat = st;
|
||||
}
|
||||
|
||||
t_stat copy_cmd (int32 flg, CONST char *cptr)
|
||||
{
|
||||
char sname[CBUFSIZE];
|
||||
COPY_CTX copy_state;
|
||||
t_stat stat;
|
||||
|
||||
memset (©_state, 0, sizeof (copy_state));
|
||||
if ((!cptr) || (*cptr == 0))
|
||||
return SCPE_2FARG;
|
||||
cptr = get_glyph_quoted (cptr, sname, 0);
|
||||
if ((!cptr) || (*cptr == 0))
|
||||
return SCPE_2FARG;
|
||||
cptr = get_glyph_quoted (cptr, copy_state.destname, 0);
|
||||
stat = sim_dir_scan (sname, sim_copy_entry, ©_state);
|
||||
if ((stat == SCPE_OK) && (copy_state.count))
|
||||
return sim_messagef (SCPE_OK, " %3d file(s) copied\n", copy_state.count);
|
||||
return copy_state.stat;
|
||||
}
|
||||
|
||||
/* Breakpoint commands */
|
||||
|
||||
t_stat brk_cmd (int32 flg, CONST char *cptr)
|
||||
@@ -6150,7 +6225,10 @@ sim_switches &= ~(SWMASK ('F') | SWMASK ('D') | SWMASK ('Q')); /* remove digest
|
||||
goto Cleanup_Return; \
|
||||
}
|
||||
|
||||
fstat (fileno (rfile), &rstat);
|
||||
if (fstat (fileno (rfile), &rstat)) {
|
||||
r = SCPE_IOERR;
|
||||
goto Cleanup_Return;
|
||||
}
|
||||
READ_S (buf); /* [V2.5+] read version */
|
||||
v40 = v35 = v32 = FALSE;
|
||||
if (strcmp (buf, save_ver40) == 0) /* version 4.0? */
|
||||
@@ -6603,7 +6681,8 @@ for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* reposition all */
|
||||
for (j = 0; j < dptr->numunits; j++) { /* seq devices */
|
||||
uptr = dptr->units + j;
|
||||
if ((uptr->flags & (UNIT_ATT + UNIT_SEQ)) == (UNIT_ATT + UNIT_SEQ))
|
||||
sim_fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
if (sim_fseek (uptr->fileref, uptr->pos, SEEK_SET))
|
||||
return sim_messagef (SCPE_IERR, "Can't seek to %u in %s for %s\n", (unsigned)uptr->pos, uptr->filename, sim_uname (uptr));
|
||||
}
|
||||
}
|
||||
stop_cpu = 0;
|
||||
@@ -6789,8 +6868,10 @@ fputc ('\n', st); /* start on a new line *
|
||||
if (v >= SCPE_BASE) /* SCP error? */
|
||||
fputs (sim_error_text (v), st); /* print it from the SCP list */
|
||||
else { /* VM error */
|
||||
fputs (sim_stop_messages [v], st); /* print the VM-specific message */
|
||||
|
||||
if (sim_stop_messages [v])
|
||||
fputs (sim_stop_messages [v], st); /* print the VM-specific message */
|
||||
else
|
||||
fprintf (st, "Unknown %s simulator stop code %d", sim_name, v);
|
||||
if ((sim_vm_fprint_stopped != NULL) && /* if a VM-specific stop handler is defined */
|
||||
(!sim_vm_fprint_stopped (st, v))) /* call it; if it returned FALSE, */
|
||||
return; /* we're done */
|
||||
@@ -6818,7 +6899,6 @@ if ((dptr != NULL) && (dptr->examine != NULL)) {
|
||||
}
|
||||
}
|
||||
fprintf (st, "\n");
|
||||
return;
|
||||
}
|
||||
|
||||
void fprint_stopped (FILE *st, t_stat v)
|
||||
@@ -7407,7 +7487,11 @@ for (i = 0, j = addr; i < sim_emax; i++, j = j + dptr->aincr) {
|
||||
SZ_LOAD (sz, sim_eval[i], uptr->filebuf, loc);
|
||||
}
|
||||
else {
|
||||
sim_fseek (uptr->fileref, (t_addr)(sz * loc), SEEK_SET);
|
||||
if (sim_fseek (uptr->fileref, (t_addr)(sz * loc), SEEK_SET)) {
|
||||
clearerr (uptr->fileref);
|
||||
reason = SCPE_IOERR;
|
||||
break;
|
||||
}
|
||||
sim_fread (&sim_eval[i], sz, 1, uptr->fileref);
|
||||
if ((feof (uptr->fileref)) &&
|
||||
!(uptr->flags & UNIT_FIX)) {
|
||||
@@ -7498,7 +7582,10 @@ for (i = 0, j = addr; i < count; i++, j = j + dptr->aincr) {
|
||||
uptr->hwmark = (uint32) loc + 1;
|
||||
}
|
||||
else {
|
||||
sim_fseek (uptr->fileref, (t_addr)(sz * loc), SEEK_SET);
|
||||
if (sim_fseek (uptr->fileref, (t_addr)(sz * loc), SEEK_SET)) {
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
sim_fwrite (&sim_eval[i], sz, 1, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) {
|
||||
clearerr (uptr->fileref);
|
||||
@@ -7816,7 +7903,7 @@ return 0;
|
||||
}
|
||||
|
||||
/* strcasecmp() is not available on all platforms */
|
||||
int sim_strcasecmp (const char* string1, const char* string2)
|
||||
int sim_strcasecmp (const char *string1, const char *string2)
|
||||
{
|
||||
size_t i = 0;
|
||||
unsigned char s1, s2;
|
||||
@@ -7842,6 +7929,71 @@ while (1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* strlcat() and strlcpy() are not available on all platforms */
|
||||
/* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> */
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t sim_strlcat(char *dst, const char *src, size_t size)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = size;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = size - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return (dlen + strlen(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
return (dlen + (s - src)); /* count does not include NUL */
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
*/
|
||||
size_t sim_strlcpy (char *dst, const char *src, size_t size)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = size;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0) {
|
||||
while (--n != 0) {
|
||||
if ((*d++ = *s++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0) {
|
||||
if (size != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
;
|
||||
}
|
||||
return (s - src - 1); /* count does not include NUL */
|
||||
}
|
||||
|
||||
/* get_yn yes/no question
|
||||
|
||||
Inputs:
|
||||
@@ -8174,6 +8326,7 @@ while (size--) {
|
||||
case '\'':
|
||||
if (quote == *iptr)
|
||||
*tptr++ = '\\';
|
||||
/* fall through */
|
||||
default:
|
||||
if (sim_isprint (*iptr))
|
||||
*tptr++ = *iptr;
|
||||
@@ -10889,7 +11042,8 @@ while (1) { /* format passed string, arg
|
||||
break;
|
||||
}
|
||||
|
||||
if (sim_do_ocptr[sim_do_depth]) {
|
||||
if ((sim_do_ocptr[sim_do_depth]) &&
|
||||
((stat & ~SCPE_NOMESSAGE) != SCPE_OK)) {
|
||||
if (!sim_do_echo && !sim_quiet && !inhibit_message)
|
||||
sim_printf("%s> %s\n", do_position(), sim_do_ocptr[sim_do_depth]);
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user