home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
modem
/
byepc300.arc
/
BYESHELL.ARC
/
SHELL.C
< prev
next >
Wrap
Text File
|
1987-10-24
|
21KB
|
1,030 lines
/*
** File: <shell.c>
**
** Purpose: Security Command Line Processor for BYE-PC
**
** Author: R.E. Starr, Jr.
**
** Date: 12/31/86
**
** Revisons: 1.04 - (03/28/87) Modified caller status word to
** allow up to 16 disk drives in system.
**
** 1.05 - (03/30/87) Modified to check for precsence
** of BYE-PC before calling any external functions.
** This allows SHELL to function without BYE-PC.
**
** 1.06 - (03/31/87) Added 'getdrive()' to read the
** current default drive instead of keeping up
** with it in a storage location.
**
** 1.07 - (04/05/87) Added redirection checking
**
** 1.08 - (05/01/87) Added command line options for
** debugging and status level settings.
**
** 1.09 - (05/01/87) Added missing drive table to map
** out invalid/non-supported drives.
**
** 1.10 - (05/08/87) Modified for byexface ver 2.00
*/
#include <stdio.h> /* std Microsoft C headers */
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include <process.h>
#include <signal.h>
#include <string.h>
#include <direct.h>
#include <dos.h>
#include <time.h>
#include "byexface.h" /* BYE-PC interface functions */
/* SHELL configuration section */
/* #define PCURS * define for dos cursor with path name */
#define MAX_DRV 'C' /* max drives in system, 16 max. (A-P) */
#define VER 1 /* SHELL Version# */
#define REV 10 /* SHELL Revision# */
#define BYE_VER 3 /* minimum BYE-PC version# required */
#define BYE_REV 0 /* minimum BYE-PC revision# required */
#define BIT_0 0x0001
#define BIT_1 0x0002
#define BIT_2 0x0004
#define BIT_3 0x0008
#define BIT_4 0x0010
#define BIT_5 0x0020
#define BIT_6 0x0040
#define BIT_7 0x0080
/* function declarations */
void commands(), intrinsic(), extrinsic();
void pset_parms(), pset_flags(), pflags_error();
int binary(), break_handler();
int drv_cmd(), null_cmd(), type_cmd(), time_cmd();
int dos_cmd(), exit_cmd(), cd_cmd(), format_cmd(), dir_cmd();
/* static data declarations */
static char Com_spec[64]; /* file spec of COMMAND.COM */
static char Errors = 0; /* # of persistant Errors */
static char Bye_flg = 1; /* BYE-PC loaded flag */
static char Debug = 0; /* BYE-PC not loaded mode */
static unsigned Cstat = 0; /* caller status level */
static unsigned Csw = 0; /* debug mode status flags */
/* ----------------------- NOTE ----------------------------*/
/* The following table is searched using a binary search */
/* and all strings must be in assending alphabetical order. */
/* ---------------------------------------------------------*/
#define PCMDS (sizeof(cmdpri) / sizeof(struct key))
#define RPATHS (sizeof(rpath) / sizeof(struct paths))
#define IPATHS (sizeof(ipath) / sizeof(struct paths))
#define MDRIVE (sizeof(mdrvs))
/* missing system drives */
char mdrvs[] = /* missing drive map */
{
'D', /* drive D: not supported */
'E', /* drive E: not supported */
};
/* intrinsic command table functions */
struct key
{
char *keyword; /* pointer to intrinsic key words */
int (*key_fxn)(); /* pointer to intrinsic functions */
};
struct key cmdpri[] = /* primary command set */
{
"ASSIGN", null_cmd,
"ATTRIB", null_cmd,
"BACKUP", null_cmd,
"BASIC", null_cmd,
"BASICA", null_cmd,
"BREAK", null_cmd,
"CD", cd_cmd,
"CHDIR", cd_cmd,
"COMMAND", null_cmd,
"COMP", null_cmd,
"COPY", null_cmd,
"CTTY", null_cmd,
"DATE", time_cmd,
"DEL", null_cmd,
"DIR", dir_cmd,
"DISKCOMP", null_cmd,
"DISKCOPY", null_cmd,
"DOS", dos_cmd,
"ERASE", null_cmd,
"EXE2BIN", null_cmd,
"EXIT", exit_cmd,
"FDISK", null_cmd,
"FORMAT", format_cmd,
"GRAFTABL", null_cmd,
"GRAPHICS", null_cmd,
"JOIN", null_cmd,
"KEYBFR", null_cmd,
"KEYBGR", null_cmd,
"KEYBIT", null_cmd,
"KEYBSP", null_cmd,
"KEYBUK", null_cmd,
"LABEL", null_cmd,
"MD", null_cmd,
"MKDIR", null_cmd,
"MODE", null_cmd,
"PATH", null_cmd,
"PRINT", null_cmd,
"PROMPT", null_cmd,
"RD", null_cmd,
"RECOVER", null_cmd,
"REN", null_cmd,
"RESTORE", null_cmd,
"RMDIR", null_cmd,
"SELECT", null_cmd,
"SET", null_cmd,
"SHARE", null_cmd,
"SHELL", null_cmd,
"SYS", null_cmd,
"TIME", time_cmd,
"TREE", null_cmd,
"TYPE", type_cmd,
"VER", null_cmd,
"VERIFY", null_cmd,
"VOL", null_cmd,
};
/* invalid and restricted DOS paths */
struct paths
{
char *path; /* pointer to paths */
};
struct paths ipath[] = /* illegal DOS path names */
{
"SYSTEM",
"DOS",
"XBBS",
};
struct paths rpath[] = /* restriced DOS path names */
{
"UPLOADS",
"PRIVATE",
};
/*
** Function: void main()
**
** Paramters: int argc;
** char *argv[];
**
** Purpose: Main shell calling routine
**
** Return: void
*/
main(argc, argv)
int argc;
char *argv[];
{
int rtn, n;
char *ptr;
char inp_buf[80];
char tmp_buf[80];
extern struct cmdpri;
Debug = 0;
Csw = 0;
pset_parms(argc, argv); /* check cmd line line flags */
if (signal(SIGINT, break_handler) == (int(*)()) -1)
printf("\nWARNING: Can't disable CTRL-BREAK interrupt!\n");
if (rtn = _bye_check(BYE_VER, BYE_REV))
{
if (rtn == 1)
{
Bye_flg = 0;
if (Debug)
printf("\nWARNING: BYE-PC not loaded - 'EXIT' to quit SHELL\n"); /* internal error */
else
exit(1);
}
else
{
printf("\nSHELL ERROR: BYE-PC "); /* internal error */
switch(rtn)
{
case 2:
printf("loaded is the wrong Version!\n");
break;
case 3:
printf("loaded is the wrong Revision!\n");
break;
default:
printf("returned invalid error code!\n");
break;
}
exit(1);
}
}
get_comspec(Com_spec); /* get file spec for COMMAND.COM */
if (Bye_flg)
{
_bye_setbreak(CTRL_BRK); /* now enable ctrl-breaks */
Cstat = _bye_getcsw(); /* get callers status */
}
else
Cstat = (Csw != NULL) ? Csw : 0xff00;
/* since we trap them here */
while(1)
{
if (Bye_flg)
Cstat = _bye_getcsw(); /* reset callers status */
if (!get_cmd(inp_buf, 63)) /* get a line from stdin */
continue;
ptr = strupr(inp_buf); /* make string upper case */
while(*ptr == ' ') /* skip over leading spaces */
*ptr++;
strcpy(inp_buf, ptr); /* remove all leading spaces */
strcpy(tmp_buf, ptr); /* make a copy of input str */
if (tmp_buf[0] == '\0') /* loop if no data entered */
continue;
printf("\n");
if (tmp_buf[1] == ':')
{
if (tmp_buf[2] == '\0')
{
drv_cmd(tmp_buf);
continue;
}
else
{
if (bad_drive(inp_buf)) /* check drive first */
continue;
*ptr++; /* execute on another drive */
*ptr++;
strcpy(tmp_buf, ptr);
}
}
if ((ptr = strchr(tmp_buf, ' ')) != NULL)
*ptr = '\0';
if ((n = binary(tmp_buf, cmdpri, PCMDS)) != EOF)
(*cmdpri[n].key_fxn)(inp_buf); /* do function internally */
else
extrinsic(inp_buf); /* DOS system call. */
}
}
/*
** Function: void extrinsic(input_string)
**
** Parms: char *input_string
**
** Purpose: Passes the string to the system to execute as
** a system command it possible.
**
** Return: void
*/
void extrinsic(input_string)
char *input_string;
{
int status;
if (!(*input_string)) /* any command to try? */
return; /* no, reuturn. */
if (bad_path(input_string, 1)) /* check for bad paths */
return;
Errors = 0; /* reset persistant error ctr */
status = system(input_string);
if (status)
printf("\n[EXEC of COMMAND.COM failed!]\n");
}
/*
** Function: void prompt()
**
** Parms: void
**
** Purpose: Shows the cursor prompt
**
** Return: void
*/
prompt()
{
#ifdef PCURS
char pathbuf[51];
if (getcwd(pathbuf, 50) == NULL) /* read current directory */
strcpy(pathbuf, "ERROR");
printf("\n[%s]==>>", pathbuf);
#else
printf("\n%c>", (char)getdrive() + 'A');
#endif
}
/*
** Function: get_cmd(buffer, len)
**
** Parms: char *buffer; -> ptr to a input buffer.
** int len; -> max input line length
**
** Purpose: Collects input from stdin and stores in buffer
**
** Return: 0 = no data or first character is a ';'
** 1 = data received from input
*/
int get_cmd(buffer, len)
char *buffer;
int len;
{
int c, i, flg, stat;
prompt(); /* display cursor */
stat = flg = 1;
c = '\0';
i = 0;
while((i < len) && flg)
{
c = getch();
switch(c)
{
case NULL:
getch();
break;
case '\b':
if (!i)
break;
printf("\b \b");
*buffer--;
i--;
break;
case '\t':
break;
case '\r':
case '\n':
if (!i)
stat = 0;
flg = 0;
break;
default:
if (c == ';' && i == 0)
stat = 0;
putch(c); /* echo the character back */
*buffer++ = c;
i++;
break;
}
}
*buffer = '\0'; /* terminate string */
if (!stat && i > 0)
stat = 0;
return(stat);
}
/*
** Function: int getdrive()
**
** Parms: void
**
** Purpose: Returns the current default disk drive (0=A, 1=B,,,).
**
** Return: drive code.
*/
int getdrive()
{
union REGS inregs, outregs;
inregs.h.ah = 0x19; /* read default drive */
intdos(&inregs, &outregs);
return((int)outregs.h.al);
}
/*
** Function: void get_comspec(buffer);
**
** Parms: char *buffer; -> storage for COMSPEC.
**
** Purpose: Gets the sytem environment variable COMSPEC.
**
** Return: void
**
*/
get_comspec(buffer)
char *buffer;
{
strcpy(buffer, getenv("COMSPEC"));
if (buffer[0] == NULL)
{
printf("\n[No COMSPEC variable in Environment!]\n");
exit(1);
}
}
/*
** Function: int break_handler()
**
** Parms: void
**
** Purpose: Traps all control breaks from local keyboard
**
** Return: void
*/
break_handler()
{
prompt();
signal(SIGINT, break_handler); /* reset break point */
}
/*
** Function: show_error()
**
** Parms: char *s; -> pointer to string
**
** Purpose: Prints an error message from a string and is delimited
** by the first space character.
**
** Return: void
*/
show_error(s)
char *s;
{
char buf[21];
char *ptr;
strncpy(buf, s, 20);
ptr = strchr(buf, ' ');
if (ptr != NULL)
*ptr = '\0';
if (Errors > 6) /* hangup on persistant hackers, we */
{ /* are through giving them warnings! */
printf("\n[LAST WARNING!]\n\n\n");
if (Bye_flg)
_bye_warmboot();
}
if (++Errors >= 2)
printf("\n[WARNING"); /* warn caller not to keep trying */
else
printf("\n[ERROR"); /* tell caller they cant do this! */
printf(": %s is not allowed!]\n", buf);
}
/*
** Function: int bad_redir(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Check for any redirection symbols
**
** Return: 1 = invalid redirection found
** 0 = no redirection found
*/
int bad_redir(s)
char *s;
{
char *p;
if (Cstat == 0xffff)
return(0);
if ((p = strpbrk(s, "<|>")) != NULL)
{
printf("\n[I/O Redirection Invalid]\n");
return(1);
}
return(0);
}
/*
** Function: int bad_drive(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Check the string for any drive extensions and test
** for any illegal drive codes. If caller status is
** FFFFh, the drive check is ignored.
**
** Return: 1 = invalid drive
** 0 = drive is ok
*/
bad_drive(s)
char *s;
{
int c, d;
char *ptr, *token;
unsigned stat;
if (Cstat == 0xffff)
return(0);
stat = ((Cstat >> 8) & 0x0F) + 1; /* get callers status */
ptr = strchr(s, (int)':'); /* any drive codes? */
while(ptr)
{
*ptr--; /* back up to drive name */
d = (int)*ptr++; /* get the drive letter */
d = toupper(d);
c = (d - '@'); /* convert to zero base */
if (c > stat || d > MAX_DRV)
{
printf("\n[Invalid Drive]\n"); /* status not high enough */
return(1);
}
if (missing_drv(d))
return(1);
*ptr++;
ptr = strchr(ptr, (int)':'); /* any drive codes? */
}
return(0);
}
/*
** Function: int missing_drv(d)
**
** Parms: char d; --> drive code to test.
**
** Purpose: Scan the missing drive table for any missing drives
** in the system. Return
**
** Return: 1 = invalid path
** 0 = path is ok
*/
int missing_drv(d)
int d;
{
int i, c;
for (i = 0; i < MDRIVE; i++)
{
c = (int)mdrvs[i];
if (toupper(d) == toupper(c))
{
printf("\n[Drive Not Supported]\n");
return(1);
}
}
return(0);
}
/*
** Function: int bad_path(s, flg)
**
** Parms: char *s; --> cmd line input string.
** int flg; --> 0=does not require starting slash
**
** Purpose: Check the string for any invalid paths. If the
** caller status word is FFFFh, the check is ignored.
**
** Return: 1 = invalid path
** 0 = path is ok
*/
bad_path(s, flg)
char *s;
int flg;
{
int i;
char *ptr;
ptr = s;
if (bad_drive(s)) /* check drive numbers */
return(1);
if (bad_redir(s)) /* check for redirection */
return(1);
if (Cstat == 0xffff) /* skip it if sysop */
return(0);
if (flg)
{
if ((ptr = strchr(s, '\\')) == NULL)
return(0);
}
for (i = 0; i < IPATHS; i++)
{
if (strstr(ptr, ipath[i].path)) /* scan for invalid paths */
{
printf("\n[Illegal Path Name]\n");
return(1);
}
}
if (!(Cstat & BIT_2))
{
for (i = 0; i < RPATHS; i++)
{
if (strstr(ptr, rpath[i].path)) /* scan for restricted paths */
{
printf("\n[Path Access Restricted]\n");
return(1);
}
}
}
return(0);
}
/*
** Function: int binary(*word, tab, n);
**
** Paramters: char *word --> pointer to string to search for
** struct tab --> command table structure
** int n --> number of commands in command table
**
** Purpose: Performs a binary search of the command table structure
** passed in the structure 'tab'. The strings are compared
** without regard to case.
**
** Return: EOF = command not found, else return the index of the
** command in the command table (0 to n).
*/
int binary(word, tab, n)
char *word;
struct key tab[];
int n;
{
int low, high, mid, cond;
low = 0;
high = n - 1;
while (low <= high)
{
mid = (low + high) / 2;
if ((cond = strcmpi(word, tab[mid].keyword)) < 0)
high = mid - 1;
else if (cond > 0)
low = mid + 1;
else
return(mid);
}
return(-1);
}
/*
** Function: null_cmd(s);
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Sends all commands that are not allowed and error msg.
**
** Return: void
*/
null_cmd(s)
char *s;
{
show_error(s);
}
/*
** Function: void dos_cmd(s);
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Executes COMMAND.COM as a child process.
**
** Return: void
*/
dos_cmd(s)
char *s;
{
int status;
if (!(Cstat & BIT_6))
{
show_error(s);
return;
}
status = spawnlp(P_WAIT, Com_spec, Com_spec, NULL);
if (status)
printf("\n[EXEC of COMMAND.COM failed!]\n");
else
printf("\nSHELL Command Processor for BYE-PC \n");
printf("Copyright MCODE Software (c) 1986, 1987\n\n");
}
/*
** Function: exit_cmd(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Exits the command processor shell to DOS.
**
** Return: void
*/
exit_cmd(s)
char *s;
{
if (Debug)
{
printf("\nExiting SHELL DEBUG Mode to DOS...\n");
}
else if (!(Cstat & BIT_7))
{
show_error(s);
return;
}
else
{
printf("\nWARNING: Exiting SHELL to DOS...\n");
}
exit(0);
}
/*
** Function: cd_cmd(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Traps all of the DOS CD commands.
**
** Return: void
*/
cd_cmd(s)
char *s;
{
int i;
if (!(Cstat & BIT_3))
{
show_error(s);
return;
}
else
{
if (bad_path(s, 0))
return(1);
extrinsic(s); /* status is ok */
}
}
/*
** Function: void drv_cmd(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Check with BYE before allowing a drive change.
**
** Return: void
*/
drv_cmd(s)
char *s;
{
int c, d;
unsigned stat;
stat = ((Cstat >> 8) & 0x0F) + 1;
d = *s; /* get drive letter */
d = toupper(d);
c = ((int)*s - '@');
if (c > stat || d > MAX_DRV)
printf("\n[Invalid Drive]\n"); /* status high enough? */
else if (missing_drv(d)) /* a missing drive? */
return(1);
else
extrinsic(s); /* status is ok */
}
/*
** Function: void fmt_cmd(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Hangup on the destructive caller.
**
** Return: void
*/
format_cmd(s)
char *s;
{
if (Bye_flg)
_bye_warmboot();
}
/*
** Function: void dir_cmd(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Checks for valid dir paths.
**
** Return: void
*/
dir_cmd(s)
char *s;
{
int c;
unsigned stat;
if (bad_path(s, 0)) /* check for any bad paths */
return;
extrinsic(s);
}
/*
** Function: void type_cmd(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Checks for valid type paths.
**
** Return: void
*/
type_cmd(s)
char *s;
{
int c;
unsigned stat;
if (bad_path(s, 0)) /* check for any bad paths */
return;
extrinsic(s);
}
/*
** Function: void time_cmd(s)
**
** Parms: char *s; --> cmd line input string.
**
** Purpose: Show the current system time.
**
** Return: void
*/
time_cmd(s)
char *s;
{
struct tm *newtime;
char *am_pm = "PM";
time_t long_time;
time(&long_time);
newtime = localtime(&long_time);
if (newtime->tm_hour < 12)
am_pm = "AM";
if (newtime->tm_hour > 12)
newtime->tm_hour -= 12;
printf("\n%.19s %s\n", asctime(newtime), am_pm);
}
/*
** Function: void pset_parms()
**
** Arguments: int cnt; --> number of command lines entered
** char *s[]; --> pointers to command line strings
**
** Purpose: Reads all of the command line options separated by
** spaces and '/' or '-' to determine valid options.
**
** Return: <none>
*/
void pset_parms(cnt, args)
int cnt;
char *args[];
{
int i;
char *token;
if (cnt <= 1)
return;
for (i = 1; i < cnt; ++i)
{
token = strtok(args[i], "/-");
while(token != (char *)NULL)
{
pset_flags(token);
token = strtok(NULL, "/-");
}
}
}
/*
** Function: void pflags_error()
**
** Arguments: char s[]; --> unknown options string
**
** Purpose: Displays the invalid options string entered at
** the command line and exits back to dos.
**
** Return: <none>
*/
void pflags_error(s)
char s[];
{
printf("\n\nBYE-PC Security SHELL Version %1d.%-2.2d\n", VER, REV);
printf("Copyright (c) 1986, 1987, MCODE Software\n\n");
printf("Valid Options:\n\n");
printf("\t-d .........Debug mode, with BYE-PC not loaded.\n");
printf("\t-s:{nnn}....Set CSW upon execution (decimal).\n");
printf("\n");
exit(1);
}
/*
** Function: void pset_parms()
**
** Arguments: int cnt; --> number of command lines entered
** char *s[]; --> pointers to command line strings
**
** Purpose: Reads all of the command line options separated by
** spaces ,'/', or a '-' to determine valid options.
**
** Syntax: -d ..........debug mode, BYEXFACE calls omitted.
** -s:{nnn} ....set caller status word to 0-65535
**
** Return: void
*/
void pset_flags(flg)
char flg[];
{
char f[65];
strcpy(f, flg); /* make a copy of the string */
strupr(f); /* make upper case */
if (!strcmp(f, "D"))
Debug = 1;
else if (!strncmp(f, "S:", 2))
Csw = (unsigned)atoi(&f[2]);
else
pflags_error(f);
}