📄 utility.c
字号:
exit (0);
default: waitpid(newpid, NULL, WUNTRACED);
}
}
else
{
if(states[0]&&(args[1]|| states[1]))
{ back_bat++;
flag=1;
}
output_num=states[2]; /////////
my_bat(args,Inputs,Outputs,states); //////
if(flag) back_bat--;
output_num=0;////////////
}
if(states[0]) exit(1);
else return 0;
}
if(states[2])// set output Redirection : use freopen()
{
get_fullpath(filepath, Outputs->filename);
outputfile=freopen(filepath, Outputs->opentype,stdout);
if(outputfile==NULL)
{ Error(-6,NULL,NULL,NULL,Outputs->filename);
if(states[0]) exit(1);
else return -4;
}
}
// check for internal/external command
if (!strcmp(args[0],"cd")) // "cd " command
my_cd(args,Inputs,states);
else if (!strcmp(args[0],"clr")||!strcmp(args[0],"clear")) // "clear" command
{ // system("clear");
if(output_num==0 )
my_clear( ); // my_clear()里,使用exec调用clear
if(args[1]|| states[1]||states[2]) // no argument is needed after "clear" Error(4,NULL,NULL,NULL,args[0]); }
else if (!strcmp(args[0],"dir")) // "dir" command
my_dir(args,Inputs,states);
else if (!strcmp(args[0],"echo")) // "echo" command
my_echo(args,Inputs,states); // ???
else if (!strcmp(args[0],"environ")) // "environ" command {
list_environ( ); if(states[1])// invalid input redirection e.g. environ <m.txt Error(-3,NULL,Inputs,states,"environ"); if(args[1]) // no argument is needed after "pwd" Error(-2,args+1,NULL,NULL,"environ"); }
else if (!strcmp(args[0],"help")||!strcmp(args[0],"?")) // "help" command
{ my_help(args,Outputs,states); /////////////////////////// if(states[1]) // no argument is needed after "pwd" Error(-3,NULL,Inputs,states,args[0]); }
else if (!strcmp(args[0],"pause")) // "pause" command
{ if(args[1]|| states[1]|| states[2]) // no argument is needed after "pause" Error(4,NULL,NULL,NULL,args[0]);
if(states[0]+back_bat==0) // ////////////////////////////////
getpass("Pause!\npress <Enter> key to continue... ");
}
else if (!strcmp(args[0],"pwd")) // "pwd" command {
show_pwd( ); if(states[1])// invalid input redirection e.g. environ <m.txt Error(-3,NULL,Inputs,states,"pwd"); if(args[1]) // no argument is needed after "pwd" Error(-2,args+1,NULL,NULL,"pwd"); }
// check for external excutive file, e.g. ls
else {
strcpy(parent,"parent=") ;
strcat(parent, getenv("shell"));
switch (newpid=fork( ))
{
case -1: Error(-9,NULL,NULL,NULL,"fork");
case 0: // execution in child process
if(states[1])// input redirection
{ get_fullpath(filepath,Inputs->filename);
inputfile= freopen(filepath,"r",stdin); // open file
if(inputfile==NULL)
{ Error(-6,NULL,NULL,NULL,Inputs->filename);
exit(1);
}
}
putenv( parent); //
execvp(args[0],args);
Error(-1,args,NULL,NULL,NULL);//
if(inputfile) fclose(inputfile); exit(0);
default: if(states[0]==0 )waitpid(newpid, NULL, WUNTRACED);
} // end 'switch'
} //end ' else'
if(outputfile)
{ fclose(outputfile);
freopen("/dev/tty","w",stdout);
}
if(states[2]>1)// more output
{ states[2]--;////
my_spawn (args, Inputs, Outputs+1,states) ;///////
}
if(states[0]) exit(0);
else return 0;
}// end function my_spawn( )
/* Function "Error" : used to report errors */
int Error(int errortype,char **args,const Redirect * IOputs,const int *states, char * msg) //
{ int i; if(isbat) // if executes from batchfile
fprintf(stderr,"***Line %d of inputfile \"%s\": ",bat_line,batchfile); switch(errortype) { case 1: fprintf(stderr,"Format Error: invlid argument '%s'(Letter %d), without openfile!\n",open,letter);// < >> > fprintf(stderr,"Type 'help redirection' to get help information abbout '<' '>>' and '>'\n"); break; case 2: fprintf(stderr,"Format Error(Letter %d): '%s' followed by invlid argument '%c'!\n", letter,open,*msg); // < >> > fprintf(stderr,"Type 'help redirection' to get help information abbout '<' '>>' and '>'\n"); break; case 0: fprintf(stderr," %s\n",msg); // break; case 3: fprintf(stderr,"Sorry: no help information about \"%s\" found in the manual of myshell!\n",msg);
fprintf(stderr,"Type \"man %s\" to search in the manual of system.\nNote: press the key <Q> to exit the search.\n",msg); break; case 4: fprintf(stderr,"Note: no argument is needed after \"%s\" , except the background-execute flag '&' .",msg); // fprintf(stderr,"Type 'help %s' to get usage abbout '%s' .\n",msg,msg); break; case 5: fprintf(stderr,"System Note: can not open more than %d files as %s !\n",MAX_OPEN,msg); break; case -1: fprintf(stderr,"System Warning: \"");
while (*args)
fprintf(stderr,"%s ",*args++);
fprintf(stderr,"\b\" is not internal command or executive file!\n");
if(isbat==0&&output_num==0)//
fprintf(stderr,"Type \"help command\" to see supported internal commands.\n"); break; //abort( ); case -2: fprintf(stderr,"Format Warning: invalid arguments \"" ) ; while(*args) fprintf(stderr,"%s ",*args++); fprintf(stderr,"\b\" after command \"%s\" ! \n",msg); break; case -3: fprintf(stderr,"Invalid input redirection: "); for(i=0;i<states[1];i++) fprintf(stderr,"\"<%s\" ",IOputs[i].filename); fprintf(stderr,"after \"%s\" !\n",msg); break; case -4: fprintf(stderr,"Invalid output redirection: "); for(i=0;i<states[1];i++) fprintf(stderr,"\"%s%s\" ",IOputs[i].opentype,IOputs[i].filename); fprintf(stderr,"after \"%s\" !\n",msg); break; case -5: fprintf(stderr,"Path Error : \"%s\": not a directory or not exist!\n",msg); break; case -6: fprintf(stderr,"File Error: can not open file \"%s\" !\n",msg); break; case -7: fprintf(stderr,"Overflow Error: the assigned dirpath is longer than permitted longth(%d)!\n",MAX_PATH); break; default: fprintf(stderr,"%s: %s\n", strerror(errno), msg); break; abort( ); } return 1;
} /* Function "my_delay" : used to delay */void my_delay(int n){ n=n*1000000; while(n--) ;}
/* Function "get_fullpath" : used to get the full path of a file or a directory */
void get_fullpath(char *fullpath,const char *shortpath) //
{
int i,j;
i=j=0;
fullpath[0]=0;
char *old_dir, *current_dir;
if(shortpath[0]=='~')// e.g. ~/os
{
strcpy(fullpath, getenv("HOME"));
j=strlen(fullpath);
i=1;
}
else if(shortpath[0]=='.'&&shortpath[1]=='.')// e.g. ../os { old_dir=getenv("PWD"); chdir("..");
current_dir=(char *)malloc(MAX_BUFFER);//分配内存空间
if(!current_dir) //如果内存空间分配失败
Error(-9,NULL,NULL,NULL,"malloc failed!");
getcwd(current_dir,MAX_BUFFER); //获取当前工作目录 strcpy(fullpath, current_dir);
j=strlen(fullpath);
i=2; chdir(old_dir); } else if(shortpath[0]=='.')// e.g. ./os { strcpy(fullpath, getenv("PWD"));
j=strlen(fullpath);
i=1; } else if(shortpath[0]!='/')// e.g. os/project1 { strcpy(fullpath, getenv("PWD")); strcat(fullpath, "/");
j=strlen(fullpath);
i=0; } strcat(fullpath+j,shortpath+i);
return;
}
/* ****************************** Command Functions ********************************** */
/* Function "my_cd" : used to execute the command "cd" */
int my_cd (char **args,const Redirect *Inputs,int *states)//
{
char dirpath[MAX_PATH], filepath[MAX_PATH], dirname[MAX_PATH]; //='\0';
char *current_dir;
int i,flag;
FILE *inputfile;
if(states[4])
{
if(args[1])///invalid arguments Error(-2,args+1,NULL,NULL,"cd"); if(--states[1]) Error(-3,NULL,Inputs+1,states,"cd");
get_fullpath(filepath,Inputs->filename);
inputfile=fopen(filepath,"r"); // open file
if(inputfile==NULL)// can not open
{ Error(-6,NULL,NULL,states,Inputs->filename);
return -2; // File Error
} fgets(dirname,MAX_PATH,inputfile); /// fclose(inputfile); args[1] = strtok(dirname," \b\n\r");//// i=2; while (( args[i] = strtok(NULL," \b\n\r") ) ) i++;
} else if (states[1]) // invalid input redirection e.g. cd /home <a.txt or cd <a.txt <b.txt Error(-3,NULL,Inputs,states,"cd");
if(args[1]) //the argument of pathname is given
{
if(args[2]) // more than one argument Error(-2,args+2,NULL,NULL,"cd");
get_fullpath(dirpath,args[1]);
} //end " if(args[1]) "
else { fprintf(stdout,"%s\n",getenv("PWD"));
return 0;
}
flag=chdir(dirpath); //改变工作目录
if(flag) //如果改变失败
{ Error(-5,NULL,NULL,states, args[1]);
return -2;
}
//如果目录改变成功,修改PWD的值
current_dir=(char *)malloc(MAX_BUFFER);//分配内存空间
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -