#include #include #include #include #include #include #include #include #include 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 \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; }