home *** CD-ROM | disk | FTP | other *** search
- /*
- ** 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);
- }
-