186 lines
5.6 KiB
C
186 lines
5.6 KiB
C
// This is a personal academic project. Dear PVS-Studio, please check it.
|
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
#include "shell.h"
|
|
|
|
cmd_t commands[] = {
|
|
{"help", help, 0, 1},
|
|
{"cat", cat, 0, 1},
|
|
{"time", time, 0, 1},
|
|
{"block", block, 1, 1},
|
|
{"unblock", unblock, 1, 1},
|
|
{"inforeg", inforeg, 0, 1},
|
|
{"excdiv", excdiv, 0, 1},
|
|
{"excop", excop, 0, 1},
|
|
{"filter", filter, 0, 1},
|
|
{"clear", clear, 1, 1},
|
|
{"cpufeatures", cpufeatures, 0, 1},
|
|
{"nice", nice, 0, 1},
|
|
{"ps", ps, 0, 1},
|
|
{"pipes", pipe, 0, 1},
|
|
{"kill", kill, 1, 1},
|
|
{"sem", sem, 0, 1},
|
|
{"quadratic", quadratic, 0, 1},
|
|
{"printmem", printmem, 0, 1},
|
|
{"phylo", phylo, 0, 1},
|
|
{"wc", wc, 0, 1},
|
|
{"loop", loop, 0, 1},
|
|
{"mem", mem, 0, 1},
|
|
{"test_mm", test_mm, 0, 1},
|
|
{"test_prio", test_prio, 0, 1},
|
|
{"test_processes", test_processes, 0, 1},
|
|
{"test_sync", test_sync, 0, 1},
|
|
{"test_no_sync", test_no_sync, 0, 1},
|
|
{NULL, NULL, 0, 0}
|
|
};
|
|
|
|
int scanfNoPrint(char *buffer) {
|
|
char c;
|
|
int i = 0;
|
|
while ((c = getChar()) != '\n' && i < SIZE - 1) {
|
|
if (c != -1) {
|
|
if (c == '\b' && i > 0) {
|
|
buffer[--i] = ' ';
|
|
backspace();
|
|
} else if (c != 0 && c != '\b') {
|
|
buffer[i++] = c;
|
|
putChar(c);
|
|
}
|
|
}
|
|
}
|
|
buffer[i] = '\0';
|
|
return i;
|
|
}
|
|
|
|
void processInput(char *input) {
|
|
int comm_flag0 = 0, comm_flag1 = 0, pipe = -1, end = -1, ampersand = -1;
|
|
char *tokens[SIZE] = {0};
|
|
tokens[0] = strstrip(input, ' ');
|
|
for (int i = 1; i < MAX_ARGS; i++) {
|
|
tokens[i] = strtok(tokens[i - 1], ' ');
|
|
if (i > 1) {
|
|
if (!strcmp(tokens[i - 1], "|"))
|
|
pipe = i - 1;
|
|
}
|
|
if (tokens[i][0] == 0) {
|
|
if (i > 1 && !strcmp(tokens[i - 1], "&")) {
|
|
ampersand = end = i - 1;
|
|
break;
|
|
}
|
|
end = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pipe != -1 && ampersand >= 0) {
|
|
printStringLen("piped processes are not able to run in background\n", 50);
|
|
return;
|
|
}
|
|
|
|
int *fd, *fd1, *fd2;
|
|
fd1 = sys_malloc(2 * sizeof(int));
|
|
fd1[0] = 0;
|
|
fd1[1] = 1;
|
|
|
|
if (pipe != -1) {
|
|
fd = sys_malloc(2 * sizeof(int));
|
|
if (sys_openPipe(fd, "pipe"))
|
|
return;
|
|
fd2 = sys_malloc(2 * sizeof(int));
|
|
|
|
fd1[0] = 0;
|
|
fd1[1] = fd[1];
|
|
fd2[0] = fd[0];
|
|
fd2[1] = 1;
|
|
}
|
|
char **argv0 = NULL;
|
|
char **argv1 = NULL;
|
|
int comm0 = -1;
|
|
int comm1 = -1;
|
|
|
|
if (pipe != -1) {
|
|
argv0 = sys_malloc(sizeof(char *) * pipe);
|
|
for (int i = 0; i < pipe; i++)
|
|
argv0[i] = tokens[i];
|
|
argv1 = sys_malloc(sizeof(char *) * (end - pipe - 1));
|
|
for (int i = pipe + 1; i < end; i++)
|
|
argv1[i - pipe - 1] = tokens[i];
|
|
} else {
|
|
argv0 = sys_malloc(sizeof(char *) * end);
|
|
for (int i = 0; i < end; i++)
|
|
argv0[i] = tokens[i];
|
|
}
|
|
for (int i = 0; commands[i].name != NULL; i++) {
|
|
if (!strcmp(tokens[0], commands[i].name)) {
|
|
comm_flag0 = 1;
|
|
comm0 = i;
|
|
break;
|
|
}
|
|
}
|
|
if (comm_flag0 && pipe != -1) {
|
|
for (int i = 0; commands[i].name != NULL; i++) {
|
|
if (!strcmp(tokens[pipe + 1], commands[i].name)) {
|
|
if (commands->isBuiltIn && ampersand) {
|
|
printStringLen("built-in commands are not able to run in background\n", 53);
|
|
return;
|
|
}
|
|
comm_flag1 = 1;
|
|
comm1 = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (comm_flag0 && (comm_flag1 || pipe == -1)) {
|
|
if (pipe != -1) {
|
|
sys_loadProcess(commands[comm0].func, commands[comm0].isForeground, pipe, argv0, fd1);
|
|
sys_loadProcess(commands[comm1].func, 0, end - pipe - 1, argv1, fd2);
|
|
} else {
|
|
if (commands[comm0].isBuiltIn)
|
|
commands[comm0].func(end, argv0);
|
|
else {
|
|
if (ampersand >= 0)
|
|
commands[comm0].isForeground = 0;
|
|
sys_loadProcess(commands[comm0].func, commands[comm0].isForeground, end, argv0, fd1);
|
|
}
|
|
}
|
|
|
|
if (commands[comm0].isForeground) {
|
|
sys_wait();
|
|
}
|
|
sys_free(argv0);
|
|
if (pipe != -1) {
|
|
sys_free(argv1);
|
|
sys_closePipe(fd1[1]);
|
|
}
|
|
}
|
|
|
|
if (!comm_flag0) {
|
|
if (*tokens[0] != 0)
|
|
incorrect_comm(tokens[0]);
|
|
} else if (!comm_flag1 && pipe != -1) {
|
|
if (*tokens[pipe + 1] != 0)
|
|
incorrect_comm(tokens[pipe + 1]);
|
|
}
|
|
}
|
|
|
|
void shell(int argc, char *argv[]) {
|
|
printStringLen("$> ", 3);
|
|
char buffer[SIZE] = {0};
|
|
|
|
while (scanfNoPrint(buffer) != 0) {
|
|
newline();
|
|
processInput(buffer);
|
|
printStringLen("$> ", 3);
|
|
}
|
|
}
|
|
|
|
void incorrect_comm(char *buffer) {
|
|
printString(buffer);
|
|
printStringLen(" is not a BottlerShell command\n", 32);
|
|
}
|
|
|
|
void incorrect_arg(char *command) {
|
|
printStringLen("Incorrect arguments for command ", 33);
|
|
printString(command);
|
|
newline();
|
|
} |