MyShell
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include<readline/readline.h>
#include <pwd.h>
#define NAME_SIZE 32
#define DIR_SIZE 64
#define COMMAND_NUM 16
#define COMMAND_LEN 64
void print_prompt();
int analyzer(char **parameter);
void help();
void common_command(char **parameter);
int isPIPE(int num, char **parameter);
void pipe_command(int num, int location, char **parameter1);
void isRedirect(int num, char **parameter, int *stdin_location, int *stdout_location);
void redirect_command(int stdin_location, int stdout_location, char **parameter);
void m_free(int offset, int num, char **parameter);
int main(int argc, char *argv[]) {
int parameter_num;
int pipe_location;
int stdin_location;
int stdout_location;
char **parameter = malloc(COMMAND_NUM * sizeof(char *));
while (1) {
print_prompt();
parameter_num = analyzer(parameter);
pipe_location = isPIPE(parameter_num, parameter);
isRedirect(parameter_num, parameter, &stdin_location, &stdout_location);
if (strcmp(*parameter, "exit") == 0) {
m_free(0, parameter_num, parameter);
break;
}
if (strcmp(*parameter, "cd") == 0) {
chdir(*(parameter + 1));
} else if (strcmp(*parameter, "help") == 0) {
help();
} else if (pipe_location != -1) {
pipe_command(parameter_num, pipe_location, parameter);
} else if (stdin_location != -1 || stdout_location != -1) {
redirect_command(stdin_location, stdout_location, parameter);
} else {
common_command(parameter);
}
m_free(0, parameter_num, parameter);
}
free(parameter);
parameter = NULL;
return 0;
}
void print_prompt() {
char *hostName = malloc(NAME_SIZE);
char *dirName = malloc(DIR_SIZE);
char *userName;
struct passwd *user_msg;
gethostname(hostName, NAME_SIZE);
getcwd(dirName, DIR_SIZE);
user_msg = getpwuid(getuid());
userName = user_msg->pw_name;
if (strcmp(userName, "root") == 0) {
printf("%s@%s:%s~#", userName, hostName, dirName);
} else {
printf("%s@%s:%s~$", userName, hostName, dirName);
}
}
int analyzer(char **parameter) {
char *message;
char *delim = " ";
char *p;
int num = 1;
message = readline(" ");
*parameter = malloc(COMMAND_LEN);
strcpy(*parameter, strtok(message, delim));
while (p = strtok(NULL, delim)) {
*(parameter + num) = malloc(COMMAND_LEN);
strcpy(*(parameter + num), p);
num++;
}
return num;
}
int isPIPE(int num, char **parameter) {
int location;
for (int i = 1; i < num - 1; ++i) {
if (strcmp(*(parameter + i), "|=|") == 0) {
location = i;
return location;
}
}
return -1;
}
void m_free(int offset, int num, char **parameter) {
for (int i = offset; i < num; i++) {
free(*(parameter + i));
*(parameter + i) = NULL;
}
}
void common_command(char **parameter) {
int pid;
pid = fork();
if (pid == -1) {
perror("getpid failed");
}
if (pid == 0) {
if (execvp(*parameter, parameter) == -1) {
perror("execl failed");
exit(1);
}
}
waitpid(pid, NULL, 0);
}
void pipe_command(int num, int location, char **parameter1) {
int fds[2];
int pid1;
int pid0;
pipe(fds);
char **parameter0 = malloc(COMMAND_NUM * sizeof(char *));
for (int i = location + 1; i < num; i++) {
*(parameter0 + i - location - 1) = malloc(COMMAND_LEN);
strcpy(*(parameter0 + i - location - 1), *(parameter1 + i));
}
*(parameter0 + num - location - 1) = NULL;
for (int i = location; i < num; i++) {
*(parameter1 + i) = NULL;
}
pid1 = fork();
if (pid1 == -1) {
perror("getpid failed");
}
if (pid1 == 0) {
dup2(fds[1], 1);
close(fds[0]);
if (execvp(*parameter1, parameter1) == -1) {
perror("execl failed");
exit(1);
}
}
waitpid(pid1, NULL, 0);
pid0 = fork();
if (pid0 == -1) {
perror("getpid failed");
}
if (pid0 == 0) {
dup2(fds[0], 0);
close(fds[1]);
if (execvp(*parameter0, parameter0) == -1) {
perror("execl failed");
exit(1);
}
}
close(fds[0]);
close(fds[1]);
waitpid(pid0, NULL, 0);
m_free(0, num - location - 2, parameter0);
free(parameter0);
parameter0 = NULL;
}
void isRedirect(int num, char **parameter, int *stdin_location, int *stdout_location) {
*stdin_location = -1;
*stdout_location = -1;
for (int i = 1; i < num - 1; ++i) {
if (strcmp(*(parameter + i), "<") == 0) {
*stdin_location = i;
}
if (strcmp(*(parameter + i), ">") == 0) {
*stdout_location = i;
}
}
}
void redirect_command(int stdin_location, int stdout_location, char **parameter) {
int pid0, pid1;
char *in_file, *out_file;
FILE *file_instream, *file_outstream;
if (stdin_location != -1) {
in_file = malloc(COMMAND_LEN);
strcpy(in_file, *(parameter + stdin_location + 1));
}
if (stdout_location != -1) {
out_file = malloc(COMMAND_LEN);
strcpy(out_file, *(parameter + stdout_location + 1));
}
if (stdin_location != -1) {
m_free(stdin_location, stdin_location + 2, parameter);
}
if (stdout_location != -1) {
m_free(stdout_location, stdout_location + 2, parameter);
}
pid0 = fork();
if (pid0 == -1) {
perror("getpid failed");
}
if (pid0 == 0) {
if (stdin_location != -1) {
file_instream = fopen(in_file, "r");
freopen(in_file, "r", stdin);
}
if (stdout_location != -1) {
file_outstream = fopen(out_file, "w+");
freopen(out_file, "w", stdout);
}
pid1 = fork();
if (pid1 == -1) {
perror("getpid failed");
}
if (pid1 == 0) {
if (execvp(*parameter, parameter) == -1) {
perror("execl failed");
exit(1);
}
}
waitpid(pid1, NULL, 0);
fclose(stdin);
fclose(stdout);
fclose(file_instream);
fclose(file_outstream);
exit(1);
}
waitpid(pid0, NULL, 0);
free(in_file);
in_file = NULL;
free(out_file);
out_file = NULL;
}
void help() {
printf("%s\n", "This is myShell!");
}