Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1485 lines
34 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*--------------------------------------------------------------*\
| ccp.c CONSOLE COMMAND PROCESSOR v1.0 |
| ========================= |
| |
| P- CP/M: A CP/M derived operating system |
| |
| Description: |
| ----------- |
| The Console Command Processor is a |
| distinct program which references |
| the BDOS to provide a human-oriented |
| interface for the console user to the |
| information maintained by the BDOS on |
| disk storage. |
| |
| created by : Tom Saulpaugh Date created: 7/13/82 |
| ---------- ------------ |
| last modified: 12/20/82 |
| ------------- |
| |
| (c) COPYRIGHT Digital Research 1982 |
| all rights reserved |
| |
\*--------------------------------------------------------------*/
/*--------------------------------------------------------------*\
| CCP Macro Definitions |
\*--------------------------------------------------------------*/
#include "ccpdef.h" /* include CCP defines */
/*--------------------------------------------------------------*\
| CP/M Builtin Command Table |
\*--------------------------------------------------------------*/
struct _cmd_tbl
{
BYTE *ident; /* command identifer field */
UWORD cmd_code; /* command code field */
}
cmd_tbl[8] = /* declare CP/M built-in table */
{
"DIR",DIRCMD,
"DIRS",DIRSCMD,
"TYPE",TYPECMD,
"REN",RENCMD,
"ERA",ERACMD,
"USER",UCMD,
"SUBMIT",SUBCMD,
NULL,-1
};
/*--------------------------------------------------------------*\
| Table of User Prompts and Messages |
\*--------------------------------------------------------------*/
BYTE msg[] = "NON-SYSTEM FILE(S) EXIST$";
BYTE msg2[] = "Enter Filename: $";
BYTE msg3[] = "Enter Old Name: $";
BYTE msg4[] = "Enter New Name: $";
BYTE msg5[] = "File already exists$";
BYTE msg6[] = "No file$";
BYTE msg7[] = "No wildcard filenames$";
BYTE msg8[] = "Syntax: REN Newfile=Oldfile$";
BYTE msg9[] = "Confirm(Y/N)? $";
BYTE msg10[] = "Enter User No: $";
BYTE msg11[] = ".SUB file not found$";
BYTE msg12[] = "User # range is [0-15]$";
BYTE msg13[] = "Too many arguments: $";
/*--------------------------------------------------------------*\
| Global Arrays & Variables |
\*--------------------------------------------------------------*/
/********************************/
BYTE load_try = FALSE; /* flag to mark a load try */
BYTE first_sub = TRUE; /* flag to save current cmd ptr */
BYTE chain_sub = FALSE; /* submit chaining flag */
extern BYTE submit; /* submit file flag */
BYTE end_of_file = FALSE; /* submit end of file flag */
BYTE dirflag = TRUE; /* used by fill_fcb(? or blanks)*/
BYTE subprompt = FALSE; /* submit file was prompted for */
extern BYTE morecmds; /* command after warmboot flag */
UWORD sub_index = ZERO; /* index for subdma buffer */
UWORD index = ZERO; /* index into cmd argument array*/
UWORD user = USER_ZERO; /* current default user number */
UWORD cur_disk = DISK_A; /* current default disk drive */
BYTE subcom[CMD_LEN+1]; /* submit command buffer */
BYTE subdma[CMD_LEN]; /* buffer to fill from sub file */
extern BYTE usercmd[CMD_LEN+2]; /* user command buffer */
BYTE *user_ptr = usercmd; /* next user command to execute */
BYTE *glb_index = usercmd; /* points to current command */
BYTE save_sub[CMD_LEN+1]; /* saves cur cmd line for submit*/
BYTE subfcb[FCB_LEN]; /* global fcb for sub files */
BYTE cmdfcb[FCB_LEN]; /* global fcb for Z8k files */
BYTE *tail = usercmd; /* pointer to command tail */
extern BYTE autost; /* autostart flag */
BYTE dma[DMA_LEN+3]; /* 128 byte dma buffer */
BYTE parm[MAX_ARGS][ARG_LEN]; /* cmd argument array */
BYTE del[] = /* CP/M-Z8K set of delimeters */
{'>','<','.',',','=','[',']',';','|','&','/','(',')','+','-','\\'};
/*--------------------------------------------------------------*\
| Function Definitions |
\*--------------------------------------------------------------*/
/********************************/
extern UWORD bdos(); /* this returns a word */
BYTE *scan_cmd(); /* this returns a ptr to a byte */
UWORD strcmp(); /* this returns a word */
UWORD decode(); /* this returns a word */
UWORD delim(); /* this returns a word */
BYTE true_char(); /* this returns a byte */
UWORD fill_fcb(); /* this returns a word */
UWORD user_cmd(); /* this returns a word */
UWORD cmd_file(); /* this returns a word */
UWORD dollar(); /* this returns a word */
UWORD comments(); /* this returns a word */
UWORD submit_cmd(); /* this returns a word */
/********************************/
LONG map_adr(); /* map a memory address */
#define cbdos(c,a) bdos(c,map_adr((long)a, 0))
/* call BDOS with address mapped*/
/* in caller's memory space */
/********************************/
VOID cr_lf() /* print a CR and a Linefeed */
/********************************/
{
bdos(CONSOLE_OUTPUT,LF);
bdos(CONSOLE_OUTPUT,CR);
}
/********************************/
UWORD strcmp(s1,s2) /* compare 2 char strings */
/********************************/
REG BYTE *s1,*s2;
{
while(*s1)
{
if(*s1 > *s2)
return(1);
if(*s1 < *s2)
return(-1);
s1++; s2++;
}
return((*s2 == NULL) ? 0 : -1);
}
/********************************/
VOID copy_cmd(com_index) /* Save the command which */
/* started a submit file */
/* Parameter substituion will */
/* need this command tail. */
/* The buffer save_sub is used */
/* to store the command. */
/********************************/
REG BYTE *com_index;
{
REG BYTE *t1,*temp;
temp = save_sub;
if(subprompt)
{
t1 = &parm[0][0];
while(*t1 != NULL)
*temp++ = *t1++;
*temp++ = ' ';
subprompt = FALSE;
}
while(*com_index != NULL && *com_index != EXLIMPT)
*temp++ = *com_index++;
*temp = NULL;
}
/********************************/
VOID prompt() /* print the CCP prompt */
/********************************/
{
REG UWORD cur_drive,cur_user_no;
BYTE buffer[3];
cur_user_no = bdos(GET_USER_NO,(long)255);
cur_drive = bdos(RET_CUR_DISK,(long)0);
cur_drive += 'A';
cr_lf();
if (cur_user_no != 0)
{
if(cur_user_no >= 10)
{
buffer[0] = '1';
cur_user_no -= 10;
buffer[1] = (cur_user_no + '0');
buffer[2] = '$';
}
else
{
buffer[0] = (cur_user_no + '0');
buffer[1] = '$';
}
cbdos(PRINT_STRING,&buffer[0]);
}
bdos(CONSOLE_OUTPUT,(long)cur_drive);
bdos(CONSOLE_OUTPUT,ARROW);
}
/********************************/
VOID echo_cmd(cmd,mode) /* echo any multiple commands */
/* or any illegal commands */
/********************************/
REG BYTE *cmd;
REG UWORD mode;
{
if(mode == GOOD && !(autost))
prompt();
while(*cmd != NULL && *cmd != EXLIMPT)
bdos(CONSOLE_OUTPUT,(long)*cmd++);
if(mode == BAD)
bdos(CONSOLE_OUTPUT,(long)'?');
else
cr_lf();
}
/********************************/
UWORD decode(cmd) /* Recognize the command as: */
/* --------- */
/* 1. Builtin */
/* 2. File */
/********************************/
REG BYTE *cmd;
{
REG UWORD i,n;
/****************************************/
/* Check for a CP/M builtin command */
/****************************************/
for(i = 0; i < 7;i++)
if (strcmp(cmd,cmd_tbl[i].ident) == MATCH)
return(cmd_tbl[i].cmd_code);
/********************************************************/
/* Check for a change of disk drive command */
/********************************************************/
i = 0;
while(i < (ARG_LEN-1) && parm[0][i] != ':')
i++;
if(i == 1 && parm[0][2] == NULL && parm[1][0] == NULL)
if((parm[0][0] - 'A' >= 0) && (parm[0][0] - 'A' <= 15))
return(CH_DISK);
if(i == 1 && ((parm[0][0] - 'A' < 0) || (parm[0][0] - 'A' > 15)))
return(-1);
if(i != 1 && parm[0][i] == ':')
return(-1);
/*****************************************************/
/* Check for Wildcard Filenames */
/* Check First Character of Filename for a Delimeter */
/*****************************************************/
if(fill_fcb(0,cmdfcb) > 0)
return(-1);
if(i == 1)
i = 2;
else
i = 0;
for(n = 0; n < sizeof del;n++)
if(parm[0][i] == del[n])
return(-1);
for(n = 0;n < ARG_LEN-1;n++)
if(parm[0][n] > NULL && parm[0][n] < ' ')
return(-1);
return(FILE);
}
/************************/
VOID check_cmd(tcmd) /* Check end of cmd */
/* for an '!' which */
/* starts another cmd */
REG BYTE *tcmd; /************************/
{
while(*tcmd != NULL && *tcmd != EXLIMPT)
tcmd++;
/*----------------------------*/
/* check for multiple command */
/* in case of a warmboot */
/*----------------------------*/
if(*tcmd++ == EXLIMPT && *tcmd != NULL)
{
morecmds = TRUE;
while(*tcmd == ' ')
tcmd++;
user_ptr = tcmd;
}
else
if(submit) /* check original cmd line */
{
if(!(end_of_file))
morecmds = TRUE;
/*--------------------------*/
else /* restore cmd to where user*/
/* ptr points to. User_ptr */
/* always points to next */
/* console command to exec */
{ /*--------------------------*/
submit = FALSE;
if(*user_ptr != NULL)
morecmds = TRUE;
}
}
else
morecmds = FALSE;
}
/************************/
VOID get_cmd(cmd,max_chars) /* Read in a command */
/*Strip off extra blanks*/
/************************/
REG BYTE *cmd;
REG LONG max_chars;
{
REG BYTE *c;
dma[0] = CMD_LEN; /* set maximum chars to read */
cbdos(READ_CONS_BUF,dma); /* then read console */
if(dma[1] != 0 && dma[2] != ';')
cr_lf();
dma[((UWORD)dma[1] & 0xFF)+2] = '\n'; /* tack on end of line char */
if(dma[2] == ';') /* ';' denotes a comment */
dma[2] = '\n';
c = &dma[2];
while(*c == ' ' || *c == TAB)
c++;
while(*c != '\n' && --max_chars > 0)
{
*cmd++ = toupper(*c);
if(*c == ' ' || *c == TAB)
while(*++c == ' ' || *c == TAB);
else
c++;
}
*cmd = NULL; /* tack a null character on the end*/
}
/************************/
BYTE *scan_cmd(com_index) /* move ptr to next cmd */
/* in the command line */
/************************/
REG BYTE *com_index;
{
while((*com_index != EXLIMPT) &&
(*com_index != NULL))
com_index++;
while(*com_index == EXLIMPT || *com_index == ' ' ||
*com_index == TAB)
com_index++;
return(com_index);
}
/************************/
VOID get_parms(cmd) /* extract cmd arguments*/
/* from command line */
REG BYTE *cmd; /************************/
{
/************************************************/
/* This function parses the command line */
/* read in by get_cmd(). The expected command */
/* from that line is put into parm[0]. All */
/* parmeters associated with the command are put*/
/* in in sequential order in parm[1],parm[2], */
/* up to parm[4]. A command ends at a NULL or */
/* an exlimation point. */
/************************************************/
REG BYTE *line; /* pointer to parm array */
REG UWORD i; /* Row Index */
REG UWORD j; /* Column Index */
line = parm;
for(i = 0; i < (MAX_ARGS * ARG_LEN); i++)
*line++ = NULL;
i = 0;
/***************************************************/
/* separate command line at blanks,exlimation pts */
/***************************************************/
while(*cmd != NULL &&
*cmd != EXLIMPT &&
i < MAX_ARGS)
{
j = 0;
while(*cmd != EXLIMPT &&
*cmd != ' ' &&
*cmd != TAB &&
*cmd != NULL)
{
if(j < (ARG_LEN-1))
parm[i][j++] = *cmd;
cmd++;
}
parm[i++][j] = NULL;
if(*cmd == ' ' || *cmd == TAB)
cmd++;
if(i == 1)
tail = cmd; /* mark the beginning of the tail */
}
}
/************************/
UWORD delim(ch) /* check ch to see */
/* if it's a delimeter */
/************************/
REG BYTE *ch;
{
if(*ch <= ' ')
return(TRUE);
switch(*ch)
{
case '>':
case '<':
case '.':
case ',':
case '=':
case ':':
case '+':
case '-':
case '&':
case '/':
case '\\':
case '|':
case '(':
case ')':
case '[':
case ']':
case ';': return(TRUE);
}
return(FALSE);
}
/************************/
BYTE true_char(ch) /* return the desired */
/* character for fcb */
/************************/
REG BYTE *ch;
{
if(*ch == '*') return('?'); /* wildcard */
if(!delim(ch)) /* ascii character */
{
index++; /* increment cmd index */
return(*ch);
}
return(' '); /* pad field with blank */
}
/************************/
UWORD fill_fcb(which_parm,fcb) /* fill the fields of */
/* the file control blk */
/************************/
REG UWORD which_parm;
REG BYTE *fcb;
{
REG BYTE *ptr;
REG BYTE fillch;
REG UWORD j,k;
*fcb = 0;
for(k = 12;k <= 35; k++) /* fill fcb with zero */
fcb[k] = ZERO;
for(k = 1;k <= 11;k++)
fcb[k] = BLANK; /* blank filename+type */
/*******************************************/
/* extract drivecode,filename and filetype */
/* from parmeter blk */
/*******************************************/
if(dirflag)
fillch = '?';
else
fillch = ' ';
index = ZERO;
ptr = fcb;
if(parm[which_parm][index] == NULL) /* no parmemters */
{
ptr++;
for(j = 1;j <= 11;j++)
*ptr++ = fillch;
*fcb = (bdos(RET_CUR_DISK,(long)0)+1);
if(dirflag)
return(11);
else
return(0);
}
if(parm[which_parm][index+1] == ':')
{
*ptr = parm[which_parm][index] - 'A' + 1;
index += 2;
if(parm[which_parm][index] == NULL)
{
ptr = &fcb[1];
for(j = 1;j <= 11;j++)
*ptr++ = fillch;
if(dirflag)
return(11);
else
return(0);
}
}
else /* fill drivecode with the default disk */
*fcb = (bdos(RET_CUR_DISK,(long)0) + 1);
ptr = fcb;
ptr++; /* set pointer to fcb filename */
for(j = 1;j <= 8;j++) /* get filename */
*ptr++ = true_char(&parm[which_parm][index]);
while((!(delim(&parm[which_parm][index])))) index++;
if(parm[which_parm][index] == PERIOD)
{
index++;
for(j = 1;j <= 3;j++) /* get extension */
*ptr++ = true_char(&parm[which_parm][index]);
}
k = 0;
for(j = 1;j <= 11;j++)
if(fcb[j] == '?') k++;
return(k); /* return the number of question marks */
}
/************************/
VOID dir_cmd(attrib) /* print out a */
/* directory listing */
/*----------------------*/
/* attrib->1 (sysfiles) */
/* attrib->0 (dirfiles) */
/************************/
REG UWORD attrib;
{
BYTE needcr_lf;
REG UWORD dir_index,file_cnt;
REG UWORD save,j,k,curdrive,exist;
j = 0; exist = FALSE; needcr_lf = FALSE;
while(parm[1][j] != NULL && parm[1][j] != ':')
j++;
if(parm[1][j] == ':' && j != 1)
{
echo_cmd(&parm[1][0],BAD);
return(0);
}
if(parm[2][0] != NULL)
{
cbdos(PRINT_STRING,&msg13[0]);
echo_cmd(&parm[2][0],BAD);
return(0);
}
if(parm[1][1] == ':')
if((parm[1][0] < 'A') ||
(parm[1][0] > 'P'))
{
echo_cmd(&parm[1][0],BAD);
return(0);
}
fill_fcb(1,cmdfcb);
curdrive = (cmdfcb[0] + 'A' - 1);
dir_index = cbdos(SEARCH_FIRST,cmdfcb);
if(dir_index == 255)
cbdos(PRINT_STRING,&msg6[0]);
save = (32 * dir_index) + 1;
file_cnt = 0;
while(dir_index != 255)
{
if(((attrib) && (dma[save+9] & 0x80)) ||
(!(attrib) && (!(dma[save+9] & 0x80))))
{
if(needcr_lf)
{
cr_lf();
needcr_lf = FALSE;
}
if(file_cnt == 0)
bdos(CONSOLE_OUTPUT,(long)curdrive);
}
else
{
exist = TRUE;
dir_index = cbdos(SEARCH_NEXT,cmdfcb);
save = (32 * dir_index) + 1;
continue;
}
dir_index = (32 * dir_index) + 1;
bdos(CONSOLE_OUTPUT,COLON);
bdos(CONSOLE_OUTPUT,BLANKS);
j = 1;
while(j <= 11)
{
if(j == 9)
bdos(CONSOLE_OUTPUT,BLANKS);
bdos(CONSOLE_OUTPUT,(long)(dma[dir_index++] & CMASK));
j++;
}
bdos(CONSOLE_OUTPUT,BLANKS);
dir_index = cbdos(SEARCH_NEXT,cmdfcb);
if(dir_index == 255)
break;
file_cnt++;
save = (32 * dir_index) + 1;
if(file_cnt == FILES_PER_LINE) /* SS 821221 */
{
file_cnt = 0;
if((attrib && (dma[save+9] & 0x80)) ||
(!(attrib) && (!(dma[save+9] & 0x80))))
cr_lf();
else
needcr_lf = TRUE;
}
} /*----------------------------------------*/
if(exist) /* if files exist that were not displayed */
/* print out a message to the console */
{ /*----------------------------------------*/
cr_lf();
if(attrib)
cbdos(PRINT_STRING,&msg[0]);
else
cbdos(PRINT_STRING,&msg[4]);
}
}
/************************/
VOID type_cmd() /* type out a file */
/* to the console */
/************************/
{
REG UWORD i;
if(parm[1][0] == NULL) /*prompt user for filename*/
{
cbdos(PRINT_STRING,&msg2[0]);
get_cmd(&parm[1][0],(long)ARG_LEN-1);
}
if(parm[2][0] != NULL)
{
cbdos(PRINT_STRING,&msg13[0]);
echo_cmd(&parm[2][0],BAD);
return(0);
}
i = 0;
while(parm[1][i] != NULL && parm[1][i] != ':')
i++;
if(parm[1][i] == ':')
{
if(i != 1 || parm[1][0] < 'A' || parm[1][0] > 'P')
{
echo_cmd(&parm[1][0],BAD);
return(0);
}
}
i = fill_fcb(1,cmdfcb); /*fill a file control block*/
if(i == 0 && parm[1][0] != NULL && (cbdos(OPEN_FILE,cmdfcb) <= 3))
{
while(cbdos(READ_SEQ,cmdfcb) == 0)
{
for(i = 0;i <= 127;i++)
if(dma[i] != EOF)
bdos(CONSOLE_OUTPUT,(long)dma[i]);
else
break;
}
cbdos(CLOSE_FILE,cmdfcb);
bdos(RESET_DRIVE,(long)cmdfcb[0]);
} else
if(parm[1][0] != NULL)
{
if(i > 0)
{
if(i == 11)
echo_cmd(&parm[1][0],BAD);
else
cbdos(PRINT_STRING,&msg7[0]);
}
else
cbdos(PRINT_STRING,&msg6[0]);
}
}
/************************/
VOID ren_cmd() /* rename a file */
/************************/
{
BYTE new_fcb[FCB_LEN];
REG UWORD i,j,k,bad_cmd;
bad_cmd = FALSE; /*-------------------------*/
if(parm[1][0] == NULL) /*prompt user for filenames*/
{ /*-------------------------*/
cbdos(PRINT_STRING,&msg3[0]);
get_cmd(&parm[3][0],(long)ARG_LEN-1);
if(parm[3][0] == NULL)
return(0);
cbdos(PRINT_STRING,&msg4[0]);
get_cmd(&parm[1][0],(long)ARG_LEN-1);
parm[2][0] = '=';
} /*--------------------------------*/
else /*check for correct command syntax*/
{ /*--------------------------------*/
i = 0;
while(parm[1][i] != '=' && parm[1][i] != NULL) i++;
if(parm[1][i] == '=')
{
if(!(i > 0 && parm[1][i+1] != NULL &&
parm[2][0] == NULL))
bad_cmd = TRUE;
}
else
if(!(parm[2][0] == '=' &&
parm[2][1] == NULL &&
parm[3][0] != NULL))
bad_cmd = TRUE;
if(!bad_cmd && parm[1][i] == '=')
{
parm[1][i] = NULL;
i++;
j = 0;
while((parm[3][j++] = parm[1][i++]) != NULL);
parm[2][0] = '=';
}
}
for(j = 1;j < 4;j += 2)
{
k = 0;
while(parm[j][k] != ':' && parm[j][k] != NULL)
k++;
if(k > 1 && parm[j][k] == ':')
bad_cmd = TRUE;
for(i = 0;i < sizeof del;i++)
if(parm[j][0] == del[i])
{
echo_cmd(&parm[j][0],BAD);
return(0);
}
}
if(!bad_cmd && parm[1][0] != NULL && parm[3][0] != NULL)
{
i = fill_fcb(1,new_fcb);
j = fill_fcb(3,cmdfcb);
if(i == 0 && j == 0)
{
if(new_fcb[0] != cmdfcb[0])
{
if(parm[1][1] == ':' && parm[3][1] != ':')
cmdfcb[0] = new_fcb[0];
else
if(parm[1][1] != ':' && parm[3][1] == ':')
new_fcb[0] = cmdfcb[0];
else
bad_cmd = TRUE;
}
if(new_fcb[0] < 1 || new_fcb[0] > 16)
bad_cmd = TRUE;
if(!(bad_cmd) && cbdos(SEARCH_FIRST,new_fcb) != 255)
cbdos(PRINT_STRING,&msg5[0]);
else{
k = 0;
for(i = 16;i <= 35;i++)
cmdfcb[i] = new_fcb[k++];
if(cmdfcb[0] < 0 || cmdfcb[0] > 15)
bad_cmd = TRUE;
if(!(bad_cmd) &&
cbdos(RENAME_FILE,cmdfcb) > 0)
cbdos(PRINT_STRING,&msg6[0]);
}
}
else
cbdos(PRINT_STRING,&msg7[0]);
}
if(bad_cmd)
cbdos(PRINT_STRING,&msg8[0]);
}
/************************/
VOID era_cmd() /* erase a file from */
/* the directory */
/************************/
{
REG UWORD i;
/*----------------------*/
if(parm[1][0] == NULL) /* prompt for a file */
{ /*----------------------*/
cbdos(PRINT_STRING,&msg2[0]);
get_cmd(&parm[1][0],(long)ARG_LEN-1);
}
if(parm[1][0] == NULL)
return(0);
if(parm[2][0] != NULL)
{
cbdos(PRINT_STRING,&msg13[0]);
echo_cmd(&parm[2][0],BAD);
return(0);
}
i = 0;
while(parm[1][i] != ':' && parm[1][i] != NULL)
i++;
if(parm[1][i] == ':')
{
if(i != 1 || parm[1][0] < 'A' || parm[1][0] > 'P' ||
parm[1][2] == NULL)
{
echo_cmd(&parm[1][0],BAD);
return(0);
}
}
i = fill_fcb(1,cmdfcb); /* fill an fcb */
if(i > 0 && !(submit)) /* no confirmation */
{ /* if submit file */
cbdos(PRINT_STRING,&msg9[0]);
parm[2][0] = bdos(CONIN,(long)0);
parm[2][0] = toupper(parm[2][0]);
cr_lf();
if(parm[2][0] != 'N' && parm[2][0] != 'Y')
return(0);
}
if(parm[2][0] != 'N')
if(cbdos(DELETE_FILE,cmdfcb) > 0)
cbdos(PRINT_STRING,&msg6[0]);
}
/************************/
UWORD user_cmd() /* change user number */
/*----------------------*/
/* update global user */
/************************/
{
REG UWORD i;
if(parm[1][0] == NULL) /* prompt for a number */
{
cbdos(PRINT_STRING,&msg10[0]);
get_cmd(&parm[1][0],(long)ARG_LEN-1);
}
if(parm[1][0] == NULL)
return(TRUE);
if(parm[2][0] != NULL)
{
cbdos(PRINT_STRING,&msg13[0]);
echo_cmd(&parm[2][0],BAD);
return(TRUE);
}
if((parm[1][0] < '0') ||
(parm[1][0] > '9'))
return(FALSE);
i = (parm[1][0] - '0');
if(i > 9)
return(FALSE);
if(parm[1][1] != NULL)
i = ((i * 10) + (parm[1][1] - '0'));
if(i < 16 && parm[1][2] == NULL)
bdos(GET_USER_NO,(long)i);
else
return(FALSE);
user = i;
return(TRUE);
}
/************************/
VOID change_cmd() /* change default */
/* disk drive */
/*----------------------*/
/* update global disk */
/************************/
{
cur_disk = (parm[0][0] - 'A');
bdos(SELECT_DISK,(long)cur_disk);
}
UWORD cmd_file(mode)
/************************/
/* */
/* SEARCH ORDER */
/* ============ */
/* */
/* 1. Z8K type on the */
/* current user # */
/* 2. BLANK type on */
/* current user # */
/* 3. SUB type on the */
/* current user # */
/* 4. Z8K type on */
/* user 0 */
/* 5. BLANK type on the */
/* user 0 */
/* 6. SUB type on */
/* user 0 */
/* */
/*----------------------*/
/* */
/* If a filetype is */
/* specified then I */
/* search the current */
/* user # then user 0 */
/* */
/************************/
UWORD mode;
{
BYTE search_flag[6],submitfile;
REG UWORD i,n,open,sub_open,ok;
open = FALSE;
sub_open = FALSE;
dirflag = FALSE;
ok = TRUE;
load_try = TRUE; /* if a warmboot occurs reset drive & user # */
submitfile = FALSE;
user = bdos(GET_USER_NO,(long)255);
cur_disk = bdos(RET_CUR_DISK,(long)0);
if(mode == SEARCH)
i = fill_fcb(0,cmdfcb);
else
i = fill_fcb(1,cmdfcb);
if(i > 0)
{
cbdos(PRINT_STRING,&msg7[0]);
return(FALSE);
}
if(cmdfcb[9] == ' ')
{
for(i = 0;i < 6;i++)
search_flag[i] = 0;
bdos(SELECT_DISK,(long)(cmdfcb[0]-1));
cmdfcb[0] = '?';
cmdfcb[12] = NULL;
i = cbdos(SEARCH_FIRST,cmdfcb);
while(i != 255)
{
i *= 32;
if(dma[i] == 0 || dma[i] == user)
{
for(n = 9;n <= 11;n++)
dma[i+n] &= CMASK;
dma[i+12] = NULL;
cmdfcb[9] = 'Z';
cmdfcb[10] = '8';
cmdfcb[11] = 'K';
if(strcmp(&cmdfcb[1],&dma[i+1]) == MATCH)
{
if(dma[i] == user)
search_flag[0] = 1;
else
search_flag[3] = 1;
}
else
{
cmdfcb[9] = ' ';
cmdfcb[10] = ' ';
cmdfcb[11] = ' ';
if(strcmp(&cmdfcb[1],&dma[i+1]) == MATCH)
{
if(dma[i] == user)
search_flag[1] = 1;
else
search_flag[4] = 1;
}
else
{
cmdfcb[9] = 'S';
cmdfcb[10] = 'U';
cmdfcb[11] = 'B';
if(strcmp(&cmdfcb[1],&dma[i+1]) == MATCH)
{
if(dma[i] == user)
search_flag[2] = 1;
else
search_flag[5] = 1;
}
}
}
}
if((mode == SEARCH && search_flag[0] == 1) ||
(mode == SUB_FILE && search_flag[2] == 1))
i = 255;
else
i = cbdos(SEARCH_NEXT,cmdfcb);
}
if(mode == SEARCH)
fill_fcb(0,cmdfcb);
else
fill_fcb(1,cmdfcb);
bdos(SELECT_DISK,(long)cur_disk);
i = 0;
if(mode == SUB_FILE)
if(search_flag[2] == 1)
i = 2;
else
i = 5;
while(i < 6 && search_flag[i] == 0)
i++;
switch(i)
{
case 3: bdos(GET_USER_NO,(long)0);
case 0: cmdfcb[9] = 'Z';
cmdfcb[10] = '8';
cmdfcb[11] = 'K';
break;
case 4: bdos(GET_USER_NO,(long)0);
case 1: break;
case 5: bdos(GET_USER_NO,(long)0);
case 2: cmdfcb[9] = 'S';
cmdfcb[10] = 'U';
cmdfcb[11] = 'B';
break;
default: ok = FALSE;
}
}
if(cmdfcb[9] == 'S' && cmdfcb[10] == 'U' && cmdfcb[11] == 'B')
submitfile = TRUE;
while(!(open) && !(sub_open) && (ok))
{
if(cbdos(OPEN_FILE,cmdfcb) <= 3)
{
if(submitfile)
{
sub_open = TRUE;
if(submit)
chain_sub = TRUE;
else
first_sub = TRUE;
for(i = 0;i < FCB_LEN;i++)
subfcb[i] = cmdfcb[i];
submit = TRUE;
end_of_file = FALSE;
}
else
open = TRUE;
}
else
if(bdos(GET_USER_NO,(long)255) == 0)
break;
else
bdos(GET_USER_NO,(long)0);
}
if(open)
{
check_cmd(glb_index);
__LOAD();
}
if(!(sub_open) && mode == SUB_FILE)
cbdos(PRINT_STRING,&msg11[0]);
bdos(GET_USER_NO,(long)user);
dirflag = TRUE;
load_try = FALSE;
return(sub_open);
}
/************************/
UWORD dollar(k,mode,com_index) /* Translate $n to */
/* nth argument on the */
/* command line */
/************************/
REG UWORD k;
REG UWORD mode;
REG BYTE *com_index;
{
REG UWORD n,j,p_index;
REG BYTE *p1;
j = sub_index;
if(k >= CMD_LEN)
{
k = 0;
if(cbdos(READ_SEQ,subfcb) != 0)
{
end_of_file = TRUE;
return(k);
}
}
if((subdma[k] >= '0') && (subdma[k] <= '9'))
{
p_index = (subdma[k] - '0');
p1 = com_index;
if(*p1++ == 'S' &&
*p1++ == 'U' &&
*p1++ == 'B' &&
*p1++ == 'M' &&
*p1++ == 'I' &&
*p1++ == 'T' &&
*p1 == ' ')
p_index++;
p1 = com_index;
for(n = 1; n <= p_index; n++)
{
while(*p1 != ' ' && *p1 != NULL)
p1++;
if(*p1 == ' ')
p1++;
}
while(*p1 != ' ' && *p1 != NULL && j < CMD_LEN)
if(mode == FILL)
subcom[j++] = *p1++;
else
bdos(CONSOLE_OUTPUT,(long)*p1++);
k++;
}
else
{
if(mode == FILL)
subcom[j++] = '$';
else
bdos(CONSOLE_OUTPUT,(long)'$');
if(subdma[k] == '$')
k++;
}
sub_index = j;
if(k >= CMD_LEN)
{
k = 0;
if(cbdos(READ_SEQ,subfcb) != 0)
end_of_file = TRUE;
}
return(k);
}
/************************/
UWORD comments(k,com_index) /* Strip and echo submit*/
/* file comments */
/************************/
REG UWORD k;
REG BYTE *com_index;
{
REG UWORD done;
done = FALSE;
prompt();
do
{
while(k < CMD_LEN &&
subdma[k] != EOF &&
subdma[k] != Cr)
{
if(subdma[k] == '$')
{
k++;
k = dollar(k,NOFILL,com_index);
}
else
bdos(CONSOLE_OUTPUT,(long)subdma[k++]);
}
if(k == CMD_LEN && subdma[k] != EOF && subdma[k] != Cr)
{
k = 0;
if(cbdos(READ_SEQ,subfcb) != 0)
{
end_of_file = TRUE;
done = TRUE;
}
}
else
{
if(subdma[k] == Cr)
{
k += 2;
if(k >= CMD_LEN)
{
k = 0;
if(cbdos(READ_SEQ,subfcb) != 0)
end_of_file = TRUE;
}
}
else
end_of_file = TRUE;
done = TRUE;
}
}while(!(done));
return(k);
}
/************************/
VOID translate(com_index) /* TRANSLATE the subfile*/
/* and fill sub buffer. */
/************************/
REG BYTE *com_index;
{
REG BYTE *p1;
REG UWORD j,n,k,p_index;
j = 0;
k = sub_index;
while(!(end_of_file) && j < CMD_LEN
&& subdma[k] != Cr && subdma[k] != EXLIMPT)
{
switch(subdma[k])
{
case ';': k = comments(k,com_index);
break;
case TAB:
case ' ': if(j > 0)
subcom[j++] = subdma[k++];
blankout: while(k < CMD_LEN &&
(subdma[k] == ' ' || subdma[k] == TAB))
k++;
if(k >= CMD_LEN)
{
k = 0;
if(cbdos(READ_SEQ,subfcb) != 0)
end_of_file = TRUE;
else
goto blankout;
}
break;
case '$': k++;
sub_index = j;
k = dollar(k,FILL,com_index);
j = sub_index;
break;
case Lf: k++;
if(k >= CMD_LEN)
{
k = 0;
if(cbdos(READ_SEQ,subfcb) != 0)
end_of_file = TRUE;
}
break;
case EOF:
end_of_file = TRUE;
break;
default: subcom[j++] = subdma[k++];
if(k >= CMD_LEN)
{
k = 0;
if(cbdos(READ_SEQ,subfcb) != 0)
end_of_file = TRUE;
}
}
}
/*------------------------------------------------------------------*/
/* TRANSLATION OF A COMMAND IS COMPLETE */
/* -Now move sub_index to next command- */
/*------------------------------------------------------------------*/
if(subdma[k] == Cr || subdma[k] == EXLIMPT)
do
{
while(k < CMD_LEN &&
(subdma[k] == Cr ||
subdma[k] == Lf ||
subdma[k] == EXLIMPT))
k++;
if(k == CMD_LEN)
{
k = 0;
if(cbdos(READ_SEQ,subfcb) != 0)
{
end_of_file = TRUE;
break;
}
}
else
{
if(subdma[k] == EOF)
end_of_file = TRUE;
break;
}
}while(TRUE);
sub_index = k;
}
/************************/
UWORD submit_cmd(com_index) /* fill up the subcom */
/* buffer */
/************************/
/*--------------------------------------------------------------*\
| |
| Submit_Cmd is a Procedure that returns exactly |
| one command from the submit file. Submit_Cmd is |
| called only when the end of file marker has not |
| been read yet. Upon leaving submit_cmd,the variable |
| sub_index points to the beginning of the next command |
| to translate and execute. The buffer subdma is used |
| to hold the UN-translated submit file contents. |
| The buffer subcom holds a translated command. |
| Comments are echoed to the screen by the procedure |
| "comments". Parameters are substituted in comments |
| as well as command lines. |
| |
\*--------------------------------------------------------------*/
REG BYTE *com_index;
{
REG UWORD i;
for(i = 0;i <= CMD_LEN;i++)
subcom[i] = NULL;
cbdos(SET_DMA_ADDR,subdma);
if(first_sub || chain_sub)
{
for(i = 0;i < CMD_LEN;i++)
subdma[i] = NULL;
if(cbdos(READ_SEQ,subfcb) != 0)
{
end_of_file = TRUE;
subcom[0] = NULL;
}
sub_index = 0;
}
if(!(end_of_file))
translate(com_index);
for(i = 0;i < CMD_LEN;i++)
subcom[i] = toupper(subcom[i]);
cbdos(SET_DMA_ADDR,dma);
}
/************************/
VOID execute_cmd(cmd) /* branch to */
/* appropriate routine */
/************************/
REG BYTE *cmd;
{
REG UWORD i,flag;
switch( decode(cmd) )
{
case DIRCMD: dir_cmd(0);
break;
case DIRSCMD: dir_cmd(1);
break;
case TYPECMD: type_cmd();
break;
case RENCMD: ren_cmd();
break;
case ERACMD: era_cmd();
break;
case UCMD: if(!(user_cmd()))
cbdos(PRINT_STRING,&msg12[0]);
break;
case CH_DISK: change_cmd();
break;
case SUBCMD: flag = SUB_FILE;
if(parm[1][0] == NULL)
{
cbdos(PRINT_STRING,&msg2[0]);
get_cmd(subdma,(long)CMD_LEN-1);
i = 0;
while(subdma[i] != ' ' &&
subdma[i] != NULL) {
parm[1][i] = subdma[i];
i++;
}
parm[1][i] = NULL;
subprompt = TRUE;
}
else
subprompt = FALSE;
if(subdma[0] == NULL)
break;
goto gosub;
case FILE: flag = SEARCH;
gosub: if(cmd_file(flag))
break;
if(flag == SUB_FILE)
break;
default : echo_cmd(&parm[0][0],BAD);
}
}
main()
{ /*---------------------*/
REG BYTE *com_index; /* cmd execution ptr */
/*---------------------*/
dirflag = TRUE; /* init fcb fill flag */
cbdos(SET_DMA_ADDR,dma); /* set system dma addr */
/*---------------------*/
if(load_try)
{
bdos(SELECT_DISK,(long)cur_disk);
bdos(GET_USER_NO,(long)user);
load_try = FALSE;
}
/*---------------------*/
if(morecmds) /* if a warmboot */
{ /* occured & there were*/
/* more cmds to do */
if(submit) /*---------------------*/
{
com_index = subcom;
submit_cmd(save_sub);
}
else
com_index = user_ptr;
morecmds = FALSE;
echo_cmd(com_index,GOOD);
}
else
{ /*----------------------*/
prompt(); /* prompt for command */
com_index = usercmd; /* set execution pointer*/
if(!(autost)) /* check autostart flag */
get_cmd(usercmd,(long)CMD_LEN);/* read a command */
else /* -------------------- */
{ /* -------------------- */
echo_cmd(usercmd,GOOD); /* echo auto cmd and */
autost = FALSE; /* turn off flag */
} /*----------------------*/
}
/*--------------------------------------------------------------*\
| |
| MAIN CCP PARSE LOOP |
| =================== |
| |
\*--------------------------------------------------------------*/
while(*com_index != NULL)
{ /*--------------------*/
glb_index = com_index; /* save for use in */
/* check_cmd call */
get_parms(com_index); /* parse command line */
if(parm[0][0] != NULL) /* ------------------ */
execute_cmd(&parm[0][0]); /* execute command */
/*--------------------*/
if(!(submit))
com_index = scan_cmd(com_index);/* inc pointer */
else
{ /*--------------------*/
if(first_sub) /* save ptr to next */
/* console command */
/*--------------------*/
{
if(subprompt)
copy_cmd(subdma);
else
copy_cmd(com_index);
com_index = subcom;
user_ptr = scan_cmd(glb_index);
submit_cmd(save_sub);
first_sub = FALSE;
}
else
if(chain_sub)
{
if(subprompt)
copy_cmd(subdma);
else
copy_cmd(com_index);
com_index = subcom;
submit_cmd(save_sub);
chain_sub = FALSE;
}
else
com_index = NULL;
while(*com_index == NULL)
{
if(end_of_file)
{
com_index = user_ptr;
submit = FALSE;
break;
}
else
{
com_index = subcom;
submit_cmd(save_sub);
}
}
}
if(*com_index != NULL)
echo_cmd(com_index,GOOD);
}
}