admin管理员组文章数量:1564167
题目详情:综合利用进程控制的相关知识,结合对shell功能的和进程间通信手段的认知,编写简易shell程序,加深操作系统的进程控制和shell接口的认识。
编程要求
1.尝试自行设计一个C语言小程序,完成最基本的shell角色:给出命令行提示符、能够逐次接受命令;对于命令分成三种,内部命令(实现help命令、cd命令、exit命令)、外部命令(常见的ls、cp等,以及其他磁盘上的可执行程序HelloWrold等,可以用同一方法处理)以及无效命令(不是上述两种命令)。
2.将上述shell进行扩展,使得你编写的shell程序具有支持管道的功能,也就是说你的shell中输入“dir | more”能够执行dir命令并将其输出通过管道将其输入传送给more作为标准输入。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <sys/wait.h>
//define定义各个变量的基本数字
#define maxn 10000
#define maxargnumber 60
#define minn 1
#define maxvarnumber 60
#define maxstrnumber 20
#define maxstring 90
#define maxstrlen 255
#define minstring 10
#define TRUE 1
#define ERROR 0
#define maxpathlen 256
#define maxbuflen 4096
#define maxcharshuzu 100
#define maxvarlen 600
#define ferror 2
#define eerror 3
struct str {
struct str* next;
int start, end, temp;
char lpoint, rpoint;
char tofile[maxpathlen], comefile[maxpathlen];
char* args[maxargnumber];
char failexec;
};
//定义备用结构体
struct com {
struct com* head;
int one, second;
};
//标记状态码
enum {
errorexit,
errorsystem,
renormal,
};
char username[maxcharshuzu];
char hostname[maxcharshuzu];
char curpath[maxcharshuzu];
struct str stri[maxstrnumber];
int strnumber, varnumber;
char conduct[maxstrlen];
char commands[maxcharshuzu][maxcharshuzu];
char var[maxvarnumber][maxpathlen];
void hanshu(int a) {
for (int i = 0; i < a; i++) {
struct com co;
co.one = i + 1;
co.second = i - 1;
}
}
int getexit() {
pid_t pid = getpid();
if (kill(pid, SIGTERM) == -1) {
return errorexit;
}
else {
return renormal;
}
}
void init(struct str* a) {
a->failexec = 0; a->temp = 0;
a->lpoint = 0; a->rpoint = 0;
a->next = NULL;
a->start = -1; a->end = -1;
for (int i = 0; i < maxargnumber; i++) {
a->args[i] = NULL;
}
}
void wrong(int a) {
switch (a) {
case ferror:
printf("进程分割错误\n");
break;
case eerror:
printf("启动其他进程错误\n");
break;
default:
printf("错误,然后退出\n");
}
exit(1);
}
int haveinput() {
int x, y; x = 0;
char z; z = 1;
while (z) {
y = maxstrlen - x;
if (y <= 0) {
printf("进程启动时间超限\n");
return -1;
}
z = 0; fgets(conduct + x, y, stdin);
while (1) {
if (conduct[x] == '\\' && conduct[x + 1] == '\n') {
z = 1;
conduct[x] = '\0';
x++;
break;
}
else if (conduct[x] == '\n') {
break;
}
x += 1;
}
}
return x;
}
int strpoint(int a) {
char x = 0; struct str* first;
for (int i = 0; i <= a; i++) {
switch (conduct[i]) {
case '&': {
if (conduct[i + 1] == ';' || conduct[i + 1] == '\n') {
conduct[i] = ' '; first->failexec = 1;
}
}
case '\t':
conduct[i] = ' ';
break;
case ';': {
x = 0;
conduct[i] = '\0';
stri[strnumber].end = i;
strnumber += 1;
break;
}
case '\n': {
conduct[i] = '\0';
stri[strnumber].end = i;
strnumber += 1;
return 0;
}
case ' ':
break;
default:
if (!x) {
x = 1; first = stri + strnumber;
stri[strnumber].start = i;
}
}
}
}
int item(char* a, char* b, int c) {
int temp = 0;
char cha;
while (b[++c] == ' ');
if (b[c] == '\n') {
return -1;
}
while (cha = a[temp] = b[c]) {
if (cha == ' ' || cha == '|' || cha == '<' || cha == '>' || cha == '\n') {
break;
}
temp += 1; c += 1;
}
a[temp] = '\0';
int com = c - 1;
return com;
}
//
int spcommand(char command[maxcharshuzu]) {
int num = 0,x;
int len = strlen(command);
for (int i = 0, x = 0; i < len; ++i) {
if (command[i] != ' ') {
commands[num][x++] = command[i];
}
else {
if (x != 0) {
commands[num][x] = '\0';
++num;
x = 0;
}
}
}
if (x != 0) {
commands[num][x] = '\0';
++num;
}
return num;
}
int checkvar(struct str* a, int b) {
char* cha = a->args[b];
int temp1 = 0, temp2 = 0;
while (cha[temp1]) {
if ((cha[temp1 - 1] != '\\') && (cha[temp1] == '$')) {
if (cha[temp1 + 1] == '{') {
temp1 += 2;
}
else temp1 += 1;
char* cha2 = &var[varnumber][temp2];
int x = 0;
while (cha2[x] = cha[temp1]) {
if (cha2[x] == '}') {
++temp1;
break;
}
if (cha2[x] == ' ' || cha2[x] == '\n' || cha2[x] == '\0')break;
x += 1; temp1 += 1;
}
cha2[x] = '\0';
cha2 = getenv(cha2);
for (int i = 0; var[varnumber][temp2++] = cha2[i++];);
temp2 -= 1;
}
else {
var[varnumber][temp2++] = cha[temp1++];
}
}
var[varnumber][temp2] = '\0';
a->args[b] = var[varnumber++];
return 0;
}
void makeusername() {
struct passwd* a = getpwuid(getuid());
strcpy(username, a->pw_name);
}
void makehostname() {
gethostname(hostname, maxpathlen);
}
int getCurWorkDir() {
char* result = getcwd(curpath, maxpathlen);
if (result == NULL)
return errorsystem;
else {
return renormal;
}
}
int mobel() {
char temp1 = 0, temp2 = 0, temp3 = 0, var = 0, c;
int one, second;
struct str* a;
for (int p = 0; p < strnumber; p++) {
if (temp1 || temp2 || temp3) {
return -1;
}
a = &stri[p];
one = a->start, second = a->end;
init(a);
for (int i = one; i < second; ++i) {
c = conduct[i];
if ((c == '\"') && (conduct[i - 1] != '\\' && (!temp2))) {
if (temp3) {
conduct[i] = temp3 = temp1 = 0;
if (var) {
var = 0;
checkvar(a, a->temp - 1);
}
}
else {
temp3 = 1;
a->args[a->temp++] = conduct + i + 1;
}
continue;
}
else if (temp3) {
if ((c == '$') && (conduct[i - 1] != '\\') && (!var)) {
var = 1;
}
continue;
}
if ((c == '\'') && (conduct[i - 1] != '\\')) {
if (temp2) {
conduct[i] = temp2 = temp1 = 0;
}
else {
temp1 = 1;
a->args[a->temp++] = conduct + i + 1;
}
continue;
}
else if (temp2) {
continue;
}
if (c == '<' || c == '>' || c == '|') {
if (temp1) {
temp1 = 0;
}
conduct[i] = '\0';
}
if (c == '<') {
if (conduct[i + 1] == '<') {
a->lpoint += 2;
conduct[i + 1] = ' ';
}
else {
a->lpoint += 1;
}
int tmp = item(a->comefile, conduct, i);
if (tmp > 0)i = tmp;
}
else if (c == '>') {
if (conduct[i + 1] == '>') {
a->rpoint += 2;
conduct[i + 1] = ' ';
}
else {
a->rpoint += 1;
}
int tmp = item(a->tofile, conduct, i);
if (tmp > 0)i = tmp;
}
else if (c == '|') {
a->end = i;
a->next = (struct str*)malloc(sizeof(struct str));
a = a->next;
init(a);
}
else if (c == ' ' || c == '\0') {
if (temp1) {
temp1 = 0;
conduct[i] = '\0';
}
}
else {
if (a->start == -1) {
a->start = i;
}
if (!temp1) {
temp1 = 1;
if ((c == '$') && (conduct[i - 1] != '\\') && (!var)) {
var = 1;
}
a->args[a->temp++] = conduct + i;
}
}
if (var) {
var = 0;
checkvar(a, a->temp - 1);
}
}
a->end = second;
}
}
int ein(struct str* a) {
if (!a->args[0])
return 0;
if (strcmp(a->args[0], "cd") == 0) {
struct stat st;
if (a->args[1]) {
stat(a->args[1], &st);
if (S_ISDIR(st.st_mode))
chdir(a->args[1]);
else {
printf("cd '%s':cd到路径是出错\n", a->args[1]);
return -1;
}
}
return 0;
}
if (strcmp(a->args[0], "pwd") == 0) {
printf("%s\n", getcwd(a->args[1], maxpathlen));
return 0;
}
if (strcmp(a->args[0], "unset") == 0) {
for (int i = 1; i < a->temp; ++i) {
unsetenv(a->args[i]);
}
return 0;
}
if (strcmp(a->args[0], "export") == 0) {
for (int i = 1; i < a->temp; ++i) {
char* val, * p;
for (p = a->args[i]; *p != '='; ++p);
*p = '\0';
val = p + 1;
setenv(a->args[i], val, 1);
}
return 0;
}
if (strcmp(a->args[0], "exit") == 0) {
exit(0);
}
return 1;
}
void IO(struct str* a, int b, int c) {
if (a->rpoint > 0) {
int flag;
if (a->rpoint == 1) {
flag = O_WRONLY | O_TRUNC | O_CREAT;
}
else {
flag = O_WRONLY | O_APPEND | O_CREAT;
}
int wport = open(a->tofile, flag);
dup2(wport, STDOUT_FILENO);
close(wport);
}
if (a->lpoint > 0) {
int rport = open(a->comefile, O_RDONLY);
dup2(rport, STDIN_FILENO);
close(rport);
}
if (b != STDIN_FILENO) {
dup2(b, STDIN_FILENO);
close(b);
}
if (c != STDOUT_FILENO) {
dup2(c, STDOUT_FILENO);
close(c);
}
}
int eout(struct str*a) {
if (!a->next) {
IO(a, STDIN_FILENO, STDOUT_FILENO);
execvp(a->args[0], a->args);
}
int fd[2];
pipe(fd);
pid_t pid = fork();
if (pid < 0) {
wrong(ferror);
}
else if (pid == 0) {
close(fd[0]);
IO(a, STDIN_FILENO, fd[1]);
execvp(a->args[0], a->args);
wrong(eerror);
}
else {
wait(NULL);
a = a->next;
close(fd[1]);
IO(a, fd[0], STDOUT_FILENO);
eout(a);
}
}
void dbug(struct str*a);
int main(){
int k,l=1;
struct com s;
for (int i = 0; i < minstring; i++) {
s.head->one = i;
s.one = i + 1;
s.second = i - 1;
}
//获得当前用户、主机名字
makeusername();
makehostname();
while (l) {
strnumber = 0;
varnumber = 0;
fflush(stdin);
int n = haveinput();
if (n <= 0) {
continue;
}
strpoint(n);
if (mobel() < 0) {
continue;
}
int status;
for (int i = 0; i < strnumber; ++i) {
struct str* a = stri+1,*temp;
status= ein(a);
if (status == 1) {
pid_t pid = fork();
if (pid == 0) {
eout(a);
}
else if (pid < 0) {
wrong(ferror);
}
if (!a->temp) {
wait(NULL);
}
a = a->next;
while (a) {
temp = a->next;
free(a);
a = temp;
}
}
}
}
return 0;
}
版权声明:本文标题:操作系统头歌实验五 Shell综合练习 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1727481941a1116923.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论