#include <sys/emx.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <string.h>
#include <malloc.h>
#include <process.h>
#include <signal.h>
#include <sys/wait.h>
static int ansi = 0;
/* input.c */
extern int get_input(char *str, int size, int opt_newline);
static char **org_env;
static char *timestr( unsigned t, char *buf )
{
sprintf( buf, "%2.2d:%02.2d", (t >> 11) & 0x1f, (t >> 5) & 0x3f);
return buf;
}
static char *datestr( unsigned d, char *buf )
{
sprintf( buf, "%2.2d-%2.2d-%2.2d", d&0x1f, (d>>5) & 0x0f, (d>>9) + 80 );
return buf;
}
static long show_filename(struct _find *pfind)
{
char timebuf[10], datebuf[10];
unsigned size = ((unsigned) pfind->size_hi << 16) + pfind->size_lo;
datestr( pfind->date, datebuf );
timestr( pfind->time, timebuf );
if (pfind->attr & (_A_SUBDIR | _A_VOLID))
printf( "%-15s <DIR>\n", pfind->name);
else
printf( "%-15s %8u %8s %8s\n",
pfind->name, size, datebuf, timebuf);
return size;
}
typedef enum {
DEFAULT, SET, ORGENV, DIR, CD, DRIVE, ECHO, CLS, DEL, HELP, EXIT
} commands;
typedef struct {
char *cp;
commands t;
} item;
static item cmds[] =
{
{ "set", SET },
{ "orgenv", ORGENV },
{ "dir", DIR },
{ "cd", CD },
{ "drive", DRIVE },
{ "echo", ECHO },
{ "del", DEL },
{ "help", HELP },
{ "exit", EXIT },
{ "cls", CLS },
{ NULL, 0 }
};
static int execute_command(char *argv[])
{
int i;
static char wild[]="*.*";
int cmd = 0;
for (i = 0; cmds[i].cp; i++)
if (stricmp(cmds[i].cp, argv[0]) == 0) {
cmd = cmds[i].t;
break;
}
if (!cmd)
cmd = DEFAULT;
switch (cmd) {
case SET:
if (argv[1]) {
char *e = malloc(strlen(argv[1]) + 2);
if (!e) return 0;
strcpy(e, argv[1]);
strupr(e);
if (putenv(e)) {
puts("Bad environmemt");
free(e);
}
}
else
for (i=0; environ[i] != NULL; i++)
puts(environ[i]);
break;
case ORGENV:
environ = org_env;
break;
case DIR:
{
struct _find info;
if (argv[1]==0)
argv[1]=wild;
if (__findfirst(argv[1],_A_NORMAL | _A_SUBDIR | _A_RDONLY, &info)) {
puts("no files found");
return 0;
}
show_filename(&info);
while (__findnext(&info) == 0)
show_filename(&info);
}
break;
case CD:
if (argv[1])
_chdir2(argv[1]);
break;
case DRIVE:
if (argv[1])
_chdrive(argv[1][0]);
break;
case ECHO:
break;
case CLS:
printf("\033[2J");
printf("\033[H");
break;
case DEL:
if (! argv[1])
return 0;
else if (strpbrk(argv[1],"*?")) {
struct _find info;
if (__findfirst(argv[1], _A_NORMAL, &info)) {
puts("no files found");
return 0;
}
else remove(info.name);
while (__findnext(&info) == 0)
remove(info.name);
}
else remove(argv[1]);
break;
case HELP:
if (ansi)
printf("\033[1;36m");
puts("shell commands: ");
puts(" set : set environment");
puts(" orgenv: restore orginal environment");
puts(" cd : change path");
puts(" drive : change drive");
puts(" dir : list directory");
puts(" del : delete files");
puts(" cls : clear screen");
puts(" exit : quit shell");
puts(" help : this text");
puts(" EMX prgs and .bat prgs");
puts("command-line: ");
puts(" Up : last command");
puts(" Home : goto begin command");
puts(" END : goto end of command");
puts(" ESC : clear command");
if (ansi)
printf("\033[0m");
break;
case EXIT:
exit(1);
case DEFAULT:
if (strlen(argv[0]) == 2 && argv[0][1] == ':') {
_chdrive(argv[0][0]);
break;
}
if (!strstr(argv[0], ".bat")) {
if (spawnvpe(P_NOWAIT, argv[0], argv, environ) == -1)
printf("error running program %s\n", argv[0]);
else
putchar('\n');
return 0;
}
} /* switch */
return 0;
}
int readline(FILE *fhandle, char *linebuf)
{
int ch;
int i = 0;
if (fhandle == stdin)
return get_input(linebuf, 512, 1);
for (;;) {
ch = fgetc(fhandle);
if (ch == EOF) {
if (i == 0)
return -1;
linebuf[i] = 0;
return i;
}
else if (ch == '\n' || ch == '\r') {
linebuf[i] = 0;
return i;
}
else if (ch=='\t' || ch=='@') {
linebuf[i++]=' ';
}
else
linebuf[i++] = ch;
}
}
int make_tokens(char *cline, char **argvec)
{
int argc, src, dst, bs, quote;
char *q;
argc = 0;
dst = src = 0;
while (cline[src] == ' ' || cline[src] == '\t' || cline[src] == '\n')
++src;
do {
if (cline[src] == 0)
q = NULL;
else {
q = cline + dst;
bs = 0;
quote = 0;
for (;;) {
if (cline[src] == '"') {
while (bs >= 2) {
cline[dst++] = '\\';
bs -= 2;
}
if (bs & 1)
cline[dst++] = '"';
else
quote = !quote;
bs = 0;
} else if (cline[src] == '\\')
++bs;
else {
while (bs != 0) {
cline[dst++] = '\\';
--bs;
}
if (cline[src] == 0 ||
((cline[src] == ' ' || cline[src] == '\t') && !quote))
break;
cline[dst++] = cline[src];
}
++src;
}
while (cline[src] == ' ' || cline[src] == '\t'
|| cline[src] == '\n')
++src;
cline[dst++] = 0;
}
argvec[argc++] = q;
} while (q != NULL);
return argc - 1;
}
#define RUN_RSX 0x1000L
static void print_version(void)
{
if (_emx_env & RUN_RSX) {
int rsx_env = _emx_rev >> 16;
int rsx_ver = _emx_rev & 0xFFFF;
if (rsx_env == 1) {
printf("\033[31m This shell is running under RSXWIN , version %X", rsx_ver);
printf("\033[0m\n");
}
else if (rsx_env == 2)
printf("This shell is running under RSXNT , version %X\n", rsx_ver);
else
printf("This shell is running under RSX , version %X\n", rsx_ver);
}
else
printf("This shell is running under EMX , revision %X\n", _emx_rev);
}
void signal_handler(int signo)
{
int rc, status;
rc = wait(&status);
if (WIFEXITED (status))
printf("Process %d exit with code %d\n", rc, WEXITSTATUS(status));
else if (WIFSTOPPED(status))
printf("Process %d stopped by signal %d\n", rc, WSTOPSIG (status));
else
printf("Process %d exit by signal %d\n", rc, WTERMSIG (status));
fflush (stdout);
}
int main(int argc, char **argv)
{
char cline[512];
char *argvec[64];
signal(SIGCLD, signal_handler);
signal(SIGINT, signal_handler);
org_env = environ;
if (getenv("TERM"))
ansi = 1;
print_version();
if (argv[1])
execute_command(argv+1);
else for (;;) {
cline[0] = _getdrive();
cline[1] = ':';
getcwd(cline+2, 256);
strlwr(cline);
if (ansi)
printf("\033[1;32m");
printf("%s> ", cline);
if (ansi)
printf("\033[1;31m");
if (readline(stdin, cline) < 0)
continue;
if (ansi)
printf("\033[0;1m");
if (!make_tokens(cline, argvec))
continue;
if (strstr(argvec[0], ".bat")) {
FILE *fd = fopen(cline, "rt");
if (!fd)
continue;
while (readline(fd, cline) >= 0) {
if (!make_tokens(cline, argvec))
continue;
execute_command(argvec);
}
fclose(fd);
}
else
execute_command(argvec);
}
return 0;
}