-
Notifications
You must be signed in to change notification settings - Fork 0
/
gwshell.c
139 lines (116 loc) · 3.29 KB
/
gwshell.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#define _GNU_SOURCE
#include <libgen.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include "gwshell.h"
int
main()
{
char *line;
char **args;
int status;
do {
/* Give the user a prompt */
gwshell_print_prompt();
/* Read and parse the input */
line = gwshell_read_line();
args = gwshell_tok_line(line);
/* Run the command */
status = gwshell_exec(args);
/* Cleanup memory */
free(line);
free(args);
} while (status >= 0);
return EXIT_SUCCESS;
}
void
gwshell_print_prompt(void)
{
printf("%s", DEFAULT_PROMPT);
}
char *
gwshell_read_line(void)
{
char *line = NULL;
size_t size = 0;
/* Read a line from the user */
getline(&line, &size, stdin);
return line;
}
char **
gwshell_tok_line(char *line)
{
int buffer = TOK_BUFSIZE;
int position = 0;
char *token;
char **tokens;
char **tokens_backup;
tokens = malloc(buffer * sizeof(char *));
if (!tokens) {
fprintf(stderr, "psh: Allocation failure :(\n");
exit(EXIT_FAILURE);
}
/* Tokenize the input string
* Can't handle spaces inside quoted strings :( */
token = strtok(line, TOK_DELIM);
while (token) {
tokens[position++] = token;
if (position >= buffer) {
/* If the new string is greater than our buffer, increase the size
* Make sure to backup the old version, in case realloc fails */
buffer += TOK_BUFSIZE;
tokens_backup = tokens;
tokens = realloc(tokens, buffer * sizeof(char *));
if (!tokens) {
/* Free the pre-realloc array and exit with failure */
free(tokens_backup);
fprintf(stderr, "psh: Allocation failure :(\n");
exit(EXIT_FAILURE);
}
}
token = strtok(NULL, TOK_DELIM);
}
tokens[position] = NULL;
return tokens;
}
/*
* Used to run a command, first checking for null commands
* You could also check for built in commands here
*/
int
gwshell_exec(char **args)
{
int i;
/* Check for empty command */
if (args[0] == NULL) return 0;
/* Simple fork/exec */
return gwshell_run(args);
}
/*
* Forks this process and runs what it has been passed
*/
int
gwshell_run(char **args)
{
pid_t pid;
int status;
int i;
/* Fork the process and execute stuff! */
pid = fork();
if (pid < 0) {
/* Can't fork :( */
} else if (pid == 0) {
/* Child process - exec the given command */
execvp(args[0], args);
} else {
do {
waitpid(pid, &status, WUNTRACED);
} while(!WIFEXITED(status) && !WIFSIGNALED(status));
}
return 0;
}