Linux大作业
newshell.c
#include"command_comm.h"
#include"err_msg.h"
#include"file_isexist.h"
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<memory.h>
#include<math.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<sys/param.h>
#include<sys/times.h>
#include<sys/time.h>
#include<pwd.h>
#include<errno.h>
#include<time.h>
#include<fcntl.h>
#include<dirent.h>
#include<signal.h>
#include<grp.h>
#include<getopt.h>
#include<utmp.h>
/*和长度有关的宏定义*/
#define MAX_LINE 80//最大命令长度
#define MAX_NAME_LEN 100//最大用户名长度
#define MAX_PATH_LEN 1000//最大路径长度
/*more*/
#define PAGELEN 24
#define LINELEN 514
/*time*/
#define err_exit(m) {perror(m); exit(1);}
/*全局变量申明*/
extern char **environ;//必须用extern申明,否则会报错
char *cmd_array[MAX_LINE/2+1];//保存命令输入,就是原框架的char* args[]
int pipe_fd[2];//和管道有关的数组,作为pipe()的参数
int cmd_cnt;//命令中字符串的个数
void readcommand();//读取用户输入
int is_internal_cmd();//处理内部命令
int is_pipe();//分析管道命令
void do_redirection();//分析重定向,对内部命令无效
void welcome();//打印欢迎信息,带有颜色
void printprompt();//打印提示符,必须包含当前路径名
int getcommandlen();//计算命令长度
void do_pipe(int pos);//执行管道命令
void run_external_cmd(int pos);//执行外部命令
int is_bg_cmd();//判断是否有后台运行符号&
void myquit();//quit,退出myshell
void myexit();//exit,直接退出
void myclr();//clr
void print_continue_info();//打印"continue"相关信息
void mypwd();//pwd,打印当前工作目录
void myecho();//echo,必须支持重定向
void myecho_redirect();//带重定向的echo
void mytime();//time,和"date"类似
void myenviron();//environ,和env一样,必须支持重定向
void myenviron_redirect();//带重定向的environ
void mycd();//cd,切换到某个目录
void myhelp();//help,必须支持重定向
void myhelp_redirect();//带有重定向的help
void print_manual();//打印用户手册,是myhelp()的子函数
void print_cmdinfo(char* cmdname);//打印每个命令的帮助信息,是myhelp()的子函数
void myexec();//exec,开启一个新进程并替换当前进程
void mytest();//test,检查文件类型,支持-l,-b,-c,-d四个选项
void myumask();//umask,查看默认的umask值或者重置umask
void myjobs();//jobs,查看正在运行的=进程
void myfg(pid_t pid);//fg,切换进程到前台
void mybg(pid_t pid);//bg,切换进程到后台
void mybatch();//实现命令批处理,一次性执行保存在文件里的命令
void mydir();//dir,显示当前目录下的所有文件
void mydir_redirect();//带有重定向的dir
/***************************功能:wc ********************************/
struct wc_option
{
unsigned char c; /* 显示字节数 */
unsigned char l; /* 显示行数 */
unsigned char w; /* 显示单词数 */
};
struct wc_count
{
unsigned int c;
unsigned int l;
unsigned int w;
};
struct wc_option g_option;
struct wc_count g_count;
static int char_is_in(char c, const char *str, size_t len)
{
size_t i;
for(i = 0; i < len; ++i)
if(str[i] == c)
return 1;
return 0;
}
static unsigned int
getwordcount(char *buf)
{
const char *word_sep = " \r\f\t\v\n";
unsigned int word_count = 0;
char *token;
size_t total_size = strlen(buf);
if(buf == NULL || buf[0] == 0)
return 0;
/* 去前面的无关字符 */
{
while(total_size > 0 && char_is_in(buf[0], word_sep, strlen(word_sep)))
{
--total_size;
buf++;
}
}
/* 去掉后面的无关字符 */
{
while(total_size > 0 && char_is_in(buf[total_size], word_sep, strlen(word_sep)))
{
buf[total_size] = 0;
--total_size;
}
}
token = strtok(buf, word_sep);
while(token)
{
++word_count;
token = strtok(NULL, word_sep);
}
return word_count;
}
static void
pr_wc(const char *file)
{
if(g_option.c == 0 && g_option.l == 0 && g_option.w == 0)
{
printf("%u\t%u\t%u\t%s\n", g_count.l, g_count.w, g_count.c, file);
return;
}
if(g_option.l != 0)
printf("%u\t", g_count.l);
if(g_option.w != 0)
printf("%u\t", g_count.w);
if(g_option.c != 0)
printf("%u\t", g_count.c);
printf("%s\n", file);
}
static int
wc(const char *file)
{
FILE *fp;
char buf[MAX_LINE_BUF_SIZE];
if(!file_isreg(file))
{
pr_msg("file [%s] is not access or is not a simple file\n", file);
return 1;
}
if((fp = fopen(file, "r")) == NULL)
{
pr_msg("open file [%s] error [%s]\n", file, strerror(errno));
return 1;
}
memset(&g_count, 0, sizeof(g_count));
while(fgets(buf, MAX_LINE_BUF_SIZE, fp) != NULL)
{
++g_count.l;
g_count.c += strlen(buf);
g_count.w += getwordcount(buf);
}
pr_wc(file);
return 0;
}
/******************************************************************/
/*******************功能:ls -l *************************************/
void show_file_info(char* filename, struct stat* info_p)
{
char* uid_to_name(), *ctime(), *gid_to_name(), *filemode();
void mode_to_letters();
char modestr[11];
mode_to_letters(info_p->st_mode, modestr);
printf("%s", modestr);
printf(" %4d", (int) info_p->st_nlink);
printf(" %-8s", uid_to_name(info_p->st_uid));
printf(" %-8s", gid_to_name(info_p->st_gid));
printf(" %8ld", (long) info_p->st_size);
printf(" %.12s", 4 + ctime(&info_p->st_mtime));
printf(" %s\n", filename);
}
void mode_to_letters(int mode, char str[])
{
strcpy(str, "----------");
if (S_ISDIR(mode))
{
str[0] = 'd';
}
if (S_ISCHR(mode))
{
str[0] = 'c';
}
if (S_ISBLK(mode))
{
str[0] = 'b';
}
if ((mode & S_IRUSR))
{
str[1] = 'r';
}
if ((mode & S_IWUSR))
{
str[2] = 'w';
}
if ((mode & S_IXUSR))
{
str[3] = 'x';
}
if ((mode & S_IRGRP))
{
str[4] = 'r';
}
if ((mode & S_IWGRP))
{
str[5] = 'w';
}
if ((mode & S_IXGRP))
{
str[6] = 'x';
}
if ((mode & S_IROTH))
{
str[7] = 'r';
}
if ((mode & S_IWOTH))
{
str[8] = 'w';
}
if ((mode & S_IXOTH))
{
str[9] = 'x';
}
}
char* uid_to_name(uid_t uid)
{
struct passwd* getpwuid(),* pw_ptr;
static char numstr[10];
if((pw_ptr = getpwuid(uid)) == NULL)
{
sprintf(numstr,"%d",uid);
return numstr;
}
else
{
return pw_ptr->pw_name;
}
}
char* gid_to_name(gid_t gid)
{
struct group* getgrgid(),* grp_ptr;
static char numstr[10];
if(( grp_ptr = getgrgid(gid)) == NULL)
{
sprintf(numstr,"%d",gid);
return numstr;
}
else
{
return grp_ptr->gr_name;
}
}
void dostat(char* filename)
{
struct stat info;
if (stat(filename, &info) == -1)
{
perror(filename);
}
else
{
show_file_info(filename, &info);
}
}
void do_ls(char dirname[])
{
DIR* dir_ptr;
struct dirent* direntp;
if ((dir_ptr = opendir(dirname)) == NULL)
{
fprintf(stderr, "ls2: cannot open %s \n", dirname);
}
else
{
while ((direntp = readdir(dir_ptr)) != NULL)
{
dostat(direntp->d_name);
}
close(dir_ptr);
}
}
/*****************************************************************/
/*************************cat,more*******************************/
void do_more(FILE *fp)
{
char line[LINELEN];
//int see_more();
int reply;
int number_line = 0;
while(fgets(line, LINELEN, fp) != NULL)
{
if(number_line == PAGELEN)
{
reply = see_more();
if(reply == 0)
break;
number_line -= reply;
}
if( fputs(line, stdout) == EOF)
exit(1);
number_line ++;
}
}
int see_more()
{
int c;
printf("\033[7m more? \033[m");
while( (c = getchar()) != EOF )
{
if(c == 'q')
return 0;
if(c == ' ')
return PAGELEN;
if(c == '\n')
return 1;
}
return 0;
}
/*****************************************************************/
/**********************who instruction*****************************/
int pr_who()
{
struct utmp *u;
char timebuf[128];
// getutent()用来从utmp 文件(/var/run/utmp)中读取一项登录数据, 该数据以utmp 结构返回。
// 第一次调用时会取得第一位用户数据, 之后每调用一次就会返回下一项数据, 直到已无任何数据时返回NULL。
while((u = getutent()))
{
/* 去除一些不需要显示的项 */
if(u->ut_type != USER_PROCESS)
continue;
ctime_r(&(u->ut_tv.tv_sec), timebuf);
if(timebuf[0] != 0)
timebuf[strlen(timebuf)-1] = 0; /*去掉'\n'*/
printf("%-12s%-12s%-20.20s (%s)\n",
u->ut_user,
u->ut_line,
timebuf,
u->ut_host);
}
endutent();
return 1;
}
/*****************************************************************/
/********************将指令写入历史文件*****************************/
int CommWriteHisFile(char *comm) //将command指令存入history文件
{
FILE *fp = NULL;
if((fp=fopen("history.txt","at+"))==NULL)
{
printf("cannot open file\n");
return 0;
}
fputs(comm,fp);
fputs("\n",fp);
//putchar(str);
fclose(fp);
fp = NULL;
return 0;
}
/*****************************************************************/
/********************从历史文件中读出指令*****************************/
void FileReadComm() //读取文件中的指令
{
FILE *stream;
char line[10];
if( (stream = fopen( "history.txt", "r" )) != NULL )
{
while(fgets(line,10,stream)!=NULL)
{
printf( "%s", line);
}
printf("\n");
fclose( stream );
}
}
/*****************************************************************/
void readcommand(){//用来读取用户输入
int exit_status = 0;
int cnt=0;//记录cmd_array[]中字符串的个数
char str[MAX_LINE]; //用户输入的字符串
char* helper;
memset(cmd_array,0,MAX_LINE/2+1);//每次必须清空!
//cmd_array
fgets(str,MAX_LINE,stdin);//用fgets代替gets,因为gets不检查溢出,比较危险
if(str[strlen(str)-1]=='\n'){
str[strlen(str)-1]='\0';//fgets会补'\n',这里必须把'\n'替换成'\0'
}
helper=strtok(str," ");//用空格分割这个命令
while(helper!=NULL){//将分割后得到的结果写进cmd_array
cmd_array[cnt]=(char*)malloc(sizeof(*helper));
strcpy(cmd_array[cnt++],helper);//注意:即便直接回车cmd_cnt也是1
helper=strtok(NULL," "); //返回被空格分开的下一个单词的首地址
}
cmd_cnt=cnt;//cmd_cnt的值就是cnt的值
}
int is_internal_cmd(){
//这个函数用来解析内部命令
//根据不同的结果来调用不同函数来达到目的
if(cmd_array[0]==NULL){//如果没有命令(只是回车)
return 0;//返回0使得主函数的continue不执行
}
else if(strcmp(cmd_array[0],"ls")==0){
CommWriteHisFile("ls");
printf("--------------rewrite\n");
do_ls(".");
return 1;
}
else if(strcmp(cmd_array[0],"cat")==0){//cat和more功能
CommWriteHisFile("cat");
printf("--------------rewrite\n");
FILE