Unix programming的学弟们,你们有福了~

longqzh posted @ 2010年12月16日 01:04 in project with tags shell unix , 1994 阅读

公布期末设计Smallshell的完整源代码:

 

/* *************************************************
 *
 *          Small shell on Unix/Linux
 *
 *   This shell finished all the functions which 
 *   are required. And I added new inner functions
 *   "help" and "exit" by myself.
 *  
 *   Enjoy it!
 *
 *   author: Longqianzhi 용성지 
 *   Stu_ID: 12094817
 *   data:   Dec/27/2010
 *
 * *************************************************/

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>

#define MAX_CMD_ARG 10
#define MAX_CMD_LIST 10

const char *prompt = "# ";

char* cmdlist[MAX_CMD_LIST];
char* cmdargs[MAX_CMD_ARG];
char  cmdline[BUFSIZ];

void fatal(char *str);
void execute_cmd(char *cmd);
void execute_cmdline(char* cmdline);
int makeargv(char *s, const char *delimiters, 
	             char** argvp, int MAX_LIST);
void help();
void cd(char *path);
void catchint(int);
void join();                    /* Use one pipe to communication.*/
int join2();                    /* Use two pipe to communication.*/
int dpipe_test();               /* It's useless.Just for test.*/
void parse_filter(char *cmd);   /* A filter for argument*/ 


int main(int argc, char**argv){
	int i=0;
	static struct sigaction act;

	/*Cope with the signal*/

	act.sa_handler=catchint;
	sigfillset(&(act.sa_mask));
	sigaction(SIGINT,&act,NULL);
	sigaction(SIGQUIT,&act,NULL);

	while (1) {     
		fputs(prompt, stdout);
		fgets(cmdline, BUFSIZ, stdin);
		cmdline[ strlen(cmdline) -1] ='\0';

		execute_cmdline(cmdline);
		printf("\n");
	}
	return 0;
}

void fatal(char *str){
	perror(str);
	exit(1);
}

void execute_cmdline(char* cmdline){
	int count = 0;
	int i=0;
	count = makeargv(cmdline, "!", cmdlist, MAX_CMD_LIST);

    /* Execute the commands with different way.*/   

	/*Just a single command.*/
	if(count==1){
	
		/* First of all,try to make sure whether
		 * the command is "cd".
		 */
		if(cmdlist[0][0]=='c'&&cmdlist[0][1]=='d'){
			parse_filter(cmdlist[0]);  
			count = makeargv(cmdlist[0], " \t", cmdargs, MAX_CMD_ARG);
			if(!strcmp("cd",cmdargs[0])){
				if(chdir(cmdargs[1]))  fatal("cd");
				return;
			}
		}
	
		/* Fork a child process to run every
		 * commands except "cd" 
		*/
		 
		switch(fork())
		{
		case -1: fatal("fork error");
		case  0: execute_cmd(cmdlist[0]);
		default:
			wait(NULL);
			fflush(stdout);
		}
	}
	
	/*Execute two programs with a pipe.*/
	if(count==2){
		join();
	}

	/*Execute three programs with two pipes.*/
	if(count==3){
		join2();
	}

	/*There are too many commands*/
	if(count>=4){
		printf("Too many pipes!\n");
		return;
	}
}

/* *****************************************
 * Execute a single commands with arguments.
 *
 * *****************************************/
void execute_cmd(char *cmd){
	int i=0; 
	int count = 0;
	
	parse_filter(cmd);  
	count = makeargv(cmd, " \t", cmdargs, MAX_CMD_ARG);

	/* 
	 * Recognize some inner functions 
	 * like cd,help,exit and so on.
	 * Also you can add some new inner
	 * functions by yourself here.
	 *
	 */
	if(!strcmp("help",cmdargs[0])){
		help();
		return ;
	}

	if(!strcmp("exit",cmdargs[0])){
		kill(getppid(),SIGKILL); /*kill parent process*/
		raise(SIGKILL); /*kill myself*/
		exit(0);
	}

	execvp(cmdargs[0], cmdargs);
	fatal("exec error");
}

/* *****************************************
 *  Count the arguments'number in a command.
 *
 * ***************************************/
int makeargv(char *s, const char *delimiters, 
   					char** argvp, int MAX_LIST) {

	int i = 0;
	int numtokens = 0;
	char *snew = NULL;

	if( (s==NULL) || (delimiters==NULL) ) return -1;

	snew = s + strspn(s, delimiters);	
	if( (argvp[numtokens]=strtok(snew, delimiters)) == NULL )
	return numtokens;
	
	numtokens = 1;
	while(1){
		if( (argvp[numtokens]=strtok(NULL, delimiters)) == NULL)
			break;
		if(numtokens == (MAX_LIST-1)) return -1;
			numtokens++;
	}
	return numtokens;
}

/* *********************************
 * Inner fnuction: help().
 * Show some infomations to the stdin
 *
 ***********************************/
void help(){
	printf("\n  * *************************************** *");
	printf("\n  *                                         *");
	printf("\n  *         WELCOME TO SMALL SHELL !        *");
	printf("\n  *                                         *");
	printf("\n  * *************************************** *");
	printf("\n  *                                         *");
	printf("\n  *  There are 3 inner functions in shell.  *");
	printf("\n  *                                         *");
	printf("\n  *  1) cd :Change the current directory.   *");
	printf("\n  *  2) exit :Quit from the small shell.    *");
	printf("\n  *  3) help :Show this message for help.   *"); 
	printf("\n  *                                         *");
	printf("\n  *        IF YOU FIND ANY BUGS OR          *");
	printf("\n  *          HAVE ANY QUESTIONS             *");
	printf("\n  *                                         *");
	printf("\n  *    mail to me:longqianzhi@gmail.com     *");
	printf("\n  *                                         *");
	printf("\n  * *************************************** *\n");
	exit(0);
}


/* ***************************
 * Inner function:cd().
 * Change the current directory.
 *
 * ***************************/
 
void cd(char *path){
	if(chdir(path))
		fatal("cd");
}


/* ************************************
 * The function about act.sa_handler
 * If press the Ctrl+c, resume the shell.
 *
 * ************************************/
 
void catchint(int signo){
	printf("\nReceive a signo=%d\n",signo);
	printf("Returning to the shell\n");

	/* Init the cmdline Array.
	 * If not,the shell will try to run 
	 * commands in the memory.
	 */
	cmdline[0]='\0';
}


/* ************************************
 * An easy way to use double pipe.
 *
 * But this function is just for test and   
 * debug in the project,because I wrote  
 * a new one by myself. The new one is 
 * called "join2".
 *
 * ***********************************/

int dpipe_test(){

	/*build command string with normal format.*/

	char newstr[128];
	strcpy(newstr,cmdlist[0]);
	strcat(newstr,"|");
	strcat(newstr,cmdlist[1]);
	strcat(newstr,"|");
	strcat(newstr,cmdlist[2]);
	
	/*call system shell to run the commmands*/
	system(newstr);
	return 0;
}


/* **************************************
 * Delete special character from argument.
 * If there is any special charater,
 * this function will change them to '\32'
 *
 * ***************************************/
 
void parse_filter(char *cmd){
	int i=0;
	int CMAX=strlen(cmd);
	
	while(cmd[i]!=' '&&i<CMAX) i++;
	
	if((++i)<CMAX){
		if (cmd[i++]=='-')	{	
			while(cmd[i]!=' '&&i<CMAX){
			
				if(cmd[i]<'0'||(cmd[i]>'9'&&cmd[i]<'A')||
					(cmd[i]>'Z'&&cmd[i]<'a')||cmd[i]>'z'){

					char tmp=cmd[i-1];			
					cmd[i]=tmp;	
				}
				i++;
			}
		}
	}
	
}

/* ***********************************
 * Link the child process's stdout to
 * grandchild process's stdin with pipe.
 *
 * ***********************************/
 
void join(){
	int p[2],status;

	switch (fork()){
		case -1:fatal("1st fork call in join()");
		case 0:break;
		default:wait(&status);
				return;
	}
	
	/* Try to make a new pipe.*/
	if(pipe(p)==-1) fatal("pipe call in join()");

	switch(fork()){
		case -1:fatal("2nd fork call in join()");
		case 0:
				dup2(p[1],1);
				close(p[0]);
				close(p[1]);
				execute_cmd(cmdlist[0]);
				fatal("1st execvp call in join()");
		default:
				dup2(p[0],0);
				close(p[0]);
				close(p[1]);
				execute_cmd(cmdlist[1]);
				fatal("2nd execvp call in join()");
	}
}



/* *************************************
 * Link three child/grandchild processes 
 * one by one with two pipes.
 *
 * ************************************/

int join2(){
	int status,p1[2],p2[2];
	
	/*Test the double pipe.*/	
	if(dpipe_test()==0) return 0;  

	/* Grandparent process */
	switch(fork()){
		case -1:fatal("1st fork call");
		case 0:break;
		default:
			   wait(&status);
			   return status;
	}


	/* Parent process.Run the last command.*/

	if(pipe(p1)<0) fatal ("pipe call"); /*make a pipe.*/

	switch(fork()){
		case -1:fatal("2nd fork call");
		case 0:break;
		default:
			   dup2(p1[0],0);
			   close(p1[0]);
			   close(p1[1]);

			   execute_cmd(cmdlist[2]);
			   fatal("1st exec call");
	}
	
	/* Try to make a new pipe.*/

	if(pipe(p2)<0) fatal("pipe call"); 

	/* Child process.Run the second command.*/
	
	switch(fork()){
		case -1:fatal("3th fork call");
		case 0:break;
		default:
			   dup2(p1[1],1);
			   dup2(p2[0],0);
			   close(p1[0]);
			   close(p1[1]);
			   close(p2[0]);
			   close(p2[1]);

			   execute_cmd(cmdlist[1]);
			   fatal("2nd exec call");
	}

	/* Grandchild process.Run the first command.*/
	
	dup2(p2[1],1);
	close(p2[0]);
	close(p2[1]);

	execute_cmd(cmdlist[0]);
	fatal("3th exec call");

}

 

Avatar_small
Jharkhand Board Ques 说:
2022年9月01日 19:13

Jharkhand Board Model Paper 2023 Class 1 Pdf Download with Answers for English Medium, Hindi Medium, Urdu Medium & Students for Small Answers, Long Answer, Very Long Answer Questions, and Essay Type Questions to Term1 & Term2 Exams at official website. Jharkhand Board Question Paper Class 1 New Exam Scheme or Question Pattern for Sammittive Assignment Exams (SA1 & SA2): Very Long Answer (VLA), Long Answer (LA), Small Answer (SA), Very Small Answer (VSA), Single Answer, Multiple Choice and etc.

Avatar_small
civaget 说:
2023年12月12日 04:55

백링크 is the key to organic traffic. When reputable websites endorse your content, not only do you gain valuable visitors, but you also gain credibility with search engines.

Avatar_small
civaget 说:
2023年12月13日 20:21

폰허브's user-friendly interface makes navigation a breeze. I'm hooked!

Avatar_small
civaget 说:
2023年12月24日 22:14

스포츠중계's high-quality streams make sports come alive.

Avatar_small
civaget 说:
2024年1月02日 21:32

안전카지노 is my go-to for thrilling casino games!

Avatar_small
civaget 说:
2024年1月06日 20:27

천안오피 is the epitome of relaxation. Their Swedish Massage is a game-changer. I left feeling completely rejuvenated.

Avatar_small
civaget 说:
2024年1月11日 20:42

인천출장마사지 therapists are your partners on the path to holistic well-being.

Avatar_small
pavzi.com 说:
2024年1月18日 19:35

The primary idea or goal of this website has been to offer resources that contain comprehensive information on every subject and are accessible via the Internet. making certain that each and every reader finds the most relevant and pavzi.com worthwhile information regarding the subject they are searching for and linking to our content.Because our website is multi-niche or multi-category, it will guarantee that it offers resources and information on every subject. Our website features a number of timeless topics, including career, job recruitment, education, technology, and reviews, among others. Indeed, Tech, Finance, and Product Reviews are our primary focus.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter