Metropoli BBS
VIEWER: rshell.c MODE: TEXT (ASCII)
#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;
}
[ RETURN TO DIRECTORY ]