#include #include #include #include #include #include #include #include #include int status = 0; void command() { unsigned termmode = TERMMODE_UNICODE | TERMMODE_SIGNAL | TERMMODE_UTF8 | TERMMODE_LINEBUFFER | TERMMODE_ECHO; settermmode(0, termmode); const size_t CWD_SIZE = 512; char cwd[CWD_SIZE]; const char* wd = getcwd(cwd, CWD_SIZE); if ( !wd ) { wd = "?"; } printf("root@sortix %s # ", wd); fflush(stdout); const size_t commandsize = 128; char command[commandsize + 1]; size_t commandused = 0; while (true) { char c; ssize_t bytesread = read(1, &c, sizeof(c)); if ( bytesread < 0 ) { error(64, errno, "read stdin"); } if ( !bytesread ) { break; } if ( !c ) { continue; } if ( c == '\n' ) { break; } if ( commandsize <= commandused ) { continue; } command[commandused++] = c; } command[commandused] = '\0'; if ( command[0] == '\0' ) { return; } if ( strcmp(command, "$?") == 0 ) { printf("%u\n", status); status = 0; return; } if ( strcmp(command, "$$") == 0 ) { printf("%u\n", getpid()); status = 0; return; } if ( strcmp(command, "$PPID") == 0 ) { printf("%u\n", getppid()); status = 0; return; } int argc = 0; const char* argv[256]; argv[0] = NULL; bool lastwasspace = true; for ( size_t i = 0; i <= commandused; i++ ) { switch ( command[i] ) { case '\0': case ' ': case '\t': case '\n': command[i] = 0; lastwasspace = true; break; default: if ( lastwasspace ) { argv[argc++] = command + i; } lastwasspace = false; } } if ( !argv[0] ) { return; } if ( strcmp(argv[0], "exit") == 0 ) { const char* status = "1"; if ( 1 < argc ) { status = argv[1]; } exit(atoi(status)); } if ( strcmp(argv[0], "cd") == 0 ) { status = 0; const char* newdir = "/"; if ( 1 < argc ) { newdir = argv[1]; } if ( chdir(newdir) ) { error(0, errno, "cd: %s", newdir); status = 1; } return; } pid_t child = fork(); if ( child < 0 ) { perror("fork"); status = 1; return; } if ( child != 0 ) { pid_t childpid = wait(&status); return; } if ( 3 <= argc ) { if ( strcmp(argv[argc-2], ">") == 0 ) { const char* file = argv[argc-1]; int outfd = open(file, O_CREAT | O_WRONLY | O_TRUNC | O_APPEND); if ( outfd < 0 ) { error(127, errno, "%s", file); exit(127); } close(1); dup(outfd); close(outfd); argc -= 2; } } argv[argc] = NULL; execv(argv[0], (char* const*) argv); error(127, errno, "%s", argv[0]); } int main(int argc, char* argv[]) { while ( true ) { command(); } }