-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuilt_in_command.c
More file actions
224 lines (207 loc) · 5.58 KB
/
built_in_command.c
File metadata and controls
224 lines (207 loc) · 5.58 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <termio.h>
#include <time.h>
#include <unistd.h>
#include "built_in_command.h"
#define MAXLEN 512
extern char pwd[MAXLEN];
extern mode_t mode;
/**
* cd_imp - cd 命令的实现,更改环境变量 PWD
*/
void cd_imp(const char *dir_path) {
if (dir_path == NULL || strcmp(dir_path, ".") == 0) {
// 如果 cd 当前目录或给定目录为空,则输出当前目录
printf("%s\n", pwd);
return;
}
// 首先判断是否为目录
struct stat buf;
stat(dir_path, &buf);
if (!S_ISDIR(buf.st_mode)) {
fprintf(stderr, "cd: %s: 没有那个文件或目录\n", dir_path);
return;
}
// 更改当前工作目录,然后修改 pwd 变量
if (chdir(dir_path) != 0) {
fprintf(stderr, "cd 发生错误\n");
return;
}
getcwd(pwd, MAXLEN);
// 更改环境变量
setenv("PWD", pwd, 1);
}
/**
* dir_imp - 列出目录 dir_path 中的内容,若 dir_path 为空,
* 则列出当前工作目录下的内容
*/
void dir_imp(char *dir_path) {
DIR *dir;
struct dirent *entry;
if (dir_path) {
dir = opendir(dir_path);
if (dir == NULL) {
fprintf(stderr, "%s 不为目录\n", dir_path);
}
} else {
dir = opendir(pwd);
}
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
printf("%s ", entry->d_name);
}
printf("\n");
closedir(dir);
}
/**
* echo_imp - 在屏幕上输出 argv 中传入的字符串
*/
void echo_imp(char *argv[]) {
char *str = argv[1];
for (int i = 1; str != NULL; i++, str = argv[i]) {
printf("%s ", str);
}
printf("\n");
}
/**
* clr_imp - 刷新屏幕,持续输出换行符清空当前屏幕,
* 然后将光标移动到最顶端
*/
void clr_imp() {
// 获取终端大小
struct winsize size;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &size) == -1) {
fprintf(stderr, "clr: 出现错误\n");
return;
}
for (int i = 0; i < size.ws_row; i++) {
printf("\n");
}
printf("\033[%dA", size.ws_row);
}
/**
* time_imp - 显示当前时间
*/
void time_imp() {
time_t current_time;
struct tm *cur_time;
time(¤t_time);
cur_time = localtime(¤t_time);
printf("%s", asctime(cur_time));
}
/**
* help_imp - 输出帮助手册
*/
void help_imp() {
printf("下面这些 shell 命令是内部定义的\n\n");
printf("help 帮助手册\n");
printf("bg [任务声明 ...]\n");
printf("fg [任务声明]\n");
printf("exit 退出 shell\n");
printf("pwd 显示当前目录\n");
printf("cd <目录> 更改当前目录\n");
printf("jobs 列出当前所有的任务\n");
printf("umask 模式]\n");
printf("test [表达式]\n");
printf("time 显示当前时间\n");
printf("echo <comment>\n");
printf("dir [目录] 列出目录的内容\n");
printf("set 显示所有的环境变量\n");
printf("clr 清屏\n");
}
/**
* set_imp - 输出所有的环境变量
*/
void set_imp(void) {
char *str = __environ[0];
for (int i = 0; str != NULL; i++, str = __environ[i]) {
printf("%s\n", str);
}
}
/**
* umask_imp - 设置创建文件时的权限,如果没有参数,则输出当前的设置
*/
void umask_imp(char *argv[]) {
if (argv[1] == NULL) { // 没有参数,输出当前的设置
printf("%u\n", mode);
return;
}
// 判断传入参数是否合法
int len = strlen(argv[1]);
if (len > 4) {
fprintf(stderr, "参数太长:最多三位\n");
return;
}
for (int i = len - 1; i >= 0; i--) {
if (argv[1][i] < '0' && argv[1][i] > '7') {
fprintf(stderr, "参数不合法,每一位只能为 0 到 7\n");
return;
}
}
// 设置
mode = atoi(argv[1]);
umask(mode);
}
/**
* is_valid_integer - 判断字符串 str 是否是合法的整数字符串
*/
int is_valid_integer(char *str) {
while (*str) {
if (*str < '0' || *str > '9') {
return 0;
}
str++;
}
return 1;
}
/**
* test_imp - test 的实现,只实现关于整数的比较
* -gt : 大于 -ge : 大于等于
* -lt : 小于 -le : 小于等于
* -eq : 等于 -ne : 不等于
*/
void test_imp(int argc, char *argv[]) {
if (argc > 4) {
fprintf(stderr, "test: 参数太多\n");
return;
} else if (argc < 4) {
fprintf(stderr, "test: 只支持二元表达式\n");
return;
}
if (!is_valid_integer(argv[1])) {
fprintf(stderr, "%s: 需要整数表达式\n", argv[1]);
return;
}
if (!is_valid_integer(argv[3])) {
fprintf(stderr, "%s: 需要整数表达式\n", argv[3]);
return;
}
char op;
int operand1 = atoi(argv[1]);
int operand2 = atoi(argv[3]);
int ret;
if (strcmp(argv[2], "-gt") == 0) {
ret = operand1 > operand2;
} else if (strcmp(argv[2], "-ge") == 0) {
ret = operand1 >= operand2;
} else if (strcmp(argv[2], "-lt") == 0) {
ret = operand1 < operand2;
} else if (strcmp(argv[2], "-le") == 0) {
ret = operand1 <= operand2;
} else if (strcmp(argv[2], "-eq") == 0) {
ret = operand1 == operand2;
} else if (strcmp(argv[2], "-ne") == 0) {
ret = operand1 != operand2;
} else {
fprintf(stderr, "%s: 未知操作符\n", argv[2]);
return;
}
printf("%s\n", ret ? "true" : "false");
}