/* Placed in the public domain 2009 by Sam Trenholme */ /* Yash: A usable command shell in under 4k (yet another shell) * * This is a simple thought experiment: How small can we make a *NIX command * line shell? This is as simple as it gets; it will run a command typed * in if it's an external command like "ls" or "cc", with arguments separated * by space; if one types in "-cd {directory}", it will go to that directory. * * CNTL-C exits the shell * * BUGS: CNTL-D reruns the previous command instead of exiting the shell. */ #define LINEMAX 80 #define ARGMAX 16 #include #include /* Given a pointer to arguments, destroy the string */ void yash_zap_args(char **zap) { int a = 0; if(zap == 0) { return; } for(a = 0; a < ARGMAX; a++) { if(zap[a] != 0) { free(zap[a]); zap[a] = 0; } } free(zap); } /* Given a line separated by whitespace, return an array of strings * of the individual arguments */ char **yash_args(char *in) { char **out = 0; int a = 0, b = 0; /* Sanity checks */ if(in == 0) { return 0; } out = malloc(ARGMAX * sizeof(char *)); for(a = 0; a < ARGMAX; a++) { out[a] = 0; } a = 0; if(out == 0) { return 0; } while(*in != 0) { if(*in != ' ' && *in != '\n') { if((out[a] = malloc(LINEMAX)) == 0) { goto catch_yash_args; } b = 0; while(b < LINEMAX - 2 && *in != ' ' && *in != 0 && *in != '\n') { out[a][b] = *in; b++; in++; } out[a][b] = 0; a++; if(a >= ARGMAX) { goto catch_yash_args; } } in++; } return out; catch_yash_args: yash_zap_args(out); return 0; } /* Meta commands for yash; right now this is just the cd command */ void yash_meta(char **args) { if(args == 0 || args[0] == 0) { return; } if(args[0][1] == 'c' && args[0][2] == 'd') { if(args[1] == 0) { chdir("/"); /* Should be $HOME, isn't */ } else { chdir(args[1]); } return; } } main() { char in[LINEMAX], **args = 0; for(;;) { printf("$ "); fgets(in,LINEMAX,stdin); args = yash_args(in); if(args != 0 && args[0] != 0) { if(*args[0] == '-') { yash_meta(args); } else if(fork()) { wait(0); } else { execvp(args[0],args); printf("Command not found\n"); exit(-1); } } yash_zap_args(args); } }