-
Notifications
You must be signed in to change notification settings - Fork 0
/
myshell.c
111 lines (93 loc) · 3.21 KB
/
myshell.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**
* The Main Program for the shell
*/
#define SHELL_PROMPT "\n=> "
#define CMD_QUIT "quit"
#define CMD_CD "cd"
#define CMD_MKDIR "mkdir"
#define MKDIR_PERM 0700
#define MSG_CD "Currently in: %s\n"
#define MSG_MKDIR "Created a new directory at: %s\n"
#define ERR_STDIN "%s: Couldn't read from STDIN or exceeded max buffer size of %d\n"
#define ERR_NOTFOUND "Could not locate executable: %s\n"
#define ERR_DEADCHILD "PID %d terminated unexpectedly\n"
#define ERR_FORK "Failed to fork!\n"
#define ERR_MKDIR "Could not create directory at path: %s\n"
#define BUF_SIZE 1024
#define ARGS_LEN 32
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "tokenize.h"
int changedir(char *);
int makedir(char *);
int main(int argc, char **argv) {
char *cmd = malloc(BUF_SIZE * sizeof(char));
char **cmd_args = malloc(ARGS_LEN * sizeof(char *));
do {
printf(SHELL_PROMPT);
if (fgets(cmd, BUF_SIZE, stdin) != NULL) {
if (strlen(cmd) > 1) {
cmd[strlen(cmd)-1] = '\0'; // Drop the \n
tokenize(cmd, " \t", cmd_args, ARGS_LEN);
if (strncmp(cmd_args[0], CMD_CD, strlen(CMD_CD)) == 0) {
changedir(cmd_args[1]);
} else if (strncmp(cmd_args[0], CMD_MKDIR, strlen(CMD_MKDIR)) == 0) {
makedir(cmd_args[1]);
} else if (strncmp(cmd_args[0], CMD_QUIT, strlen(CMD_QUIT)) == 0) {
// Do nothing, we'll be quitting the shell now
} else {
pid_t pid = fork();
if (pid == 0) {
// Executed by Child
execvp(*cmd_args, cmd_args);
// If the following lines are executed,
// then the command didn't exist
printf(ERR_NOTFOUND, cmd_args[0]);
cmd_args[0] = CMD_QUIT;
} else if (pid > 0) {
// Executed by Parent
int status;
pid_t cpid = wait(&status);
status = status & 0x0F; // Last 8 bits of status are 0 for
// successful exit
if (status != 0) {
printf(ERR_DEADCHILD, cpid);
}
} else {
// Failed to fork a Child
printf(ERR_FORK);
}
}
}
} else {
printf(ERR_STDIN, argv[0], BUF_SIZE);
}
} while (
cmd_args[0] == NULL ||
strncmp(cmd_args[0], CMD_QUIT, strlen(CMD_QUIT)) != 0
);
free(cmd);
free(cmd_args);
return 0;
}
int changedir(char *path) {
if (path == NULL) {
printf(MSG_CD, getcwd(path, sizeof(path)));
free(path);
} else {
return chdir(path);
}
return 0;
}
int makedir(char *path) {
if (mkdir(path, MKDIR_PERM) == -1) {
printf(ERR_MKDIR, path);
} else {
printf(MSG_MKDIR, path);
}
return 0;
}