您的位置:首页 > 运维架构 > Shell

linux入门:编写一个简单的shell(仅支持部分ls,ps命令)

2015-04-21 15:55 781 查看
实验要求:
编写一个最基本的shell服务,实现基本的类ls和类ps命令。

实验结果:
一个简单的shell
识别命令:
ls
ls(地址)
不输出隐藏文件夹/文件
ls-a (地址)
输出隐藏文件夹/文件
//可识别地址中的“~”
ps
输出为ps-A的结果
q
退出

源文件:
shell
-----src
---shell.c//含main与main_loop函数,对输入进行识别判断,调用其它函数进行处理。
---ls.c//含cmd_ls及相关函数
---ps.c//含cmd_ps及相关函数
-----include
---shell.h//包含所有所需的头文件
---ls.h//供调用cmd_ls
---ps.h//含有一个结构体procinfo,对应/proc/%d/stat文件的内容,这一结构体来源于互联网资源。

源代码:
//<src>部分

//shell.c

#include"shell.h"

//主循环,读入并解析指令

intmain_loop()

{

charcmd[100];

while(1){

printf(">");

fgets(cmd,40,stdin);

intsize=strlen(cmd);

cmd[size-1]='\0';

char*p=strtok(cmd," ");

if(strcmp(p,"ls")==0){

p=strtok(NULL,"");

if(p==NULL)

cmd_ls(".",0);

else

if(strcmp(p,"-a")==0){

p=strtok(NULL,"");

if(p==NULL)

cmd_ls(".",1);

elsecmd_ls(p,1);

}

elsecmd_ls(p,0);

}else if(strcmp(p,"ps")==0){

cmd_ps();

}

elseif(strcmp(p,"q")==0)

break;

elseprintf("command undetected\n");

}

return0;

}

intmain()

{

printf("welcometo leejf_shell!\n");

main_loop();

printf("GoodBye! ^_^");

return0;

}

//ls.c

#include"shell.h"

intcmd_ls(char *dirname,int type)//遍历目录下的文件及文件及输出名称

{

DIR*p_dir;

structdirent *p_dirent;

//替换目录中的“~”

if(dirname[0]=='~'){

structpasswd *pwd;

pwd=getpwuid(getuid());

chartmp[100]="/home/";

strcat(tmp,pwd->pw_name);

strcat(tmp,dirname+1);

dirname=tmp;

}

if((p_dir=opendir(dirname))==NULL){

fprintf(stderr,"---->can\'topen %s\n",dirname);

return0;

}

//遍历文件与文件夹

while((p_dirent=readdir(p_dir))){

char*tmp=p_dirent->d_name;

if(!strcmp(tmp,".")||!strcmp(tmp,".."))

continue;

if(type==0&&tmp[0]=='.')

continue;

printf("%s\n",tmp);

}

closedir(p_dir);

return1;

}

//ps.c

#include"shell.h"

#include"ps.h"

intdigit(char *name)//判断文件名是否为数字

{

intsize,i;

size=strlen(name);

if(size==0)return 0;

for(i=0;i<size;i++)

if(name[i]<'0'||name[i]>'9')return 0;

return1;

}

voidgetinfo(char *name,procinfo *pinfo)//对一个进程的stat文件,读取其中的信息。

//这部分做得很完整。然而输出时只输出了极少的信息。可扩 //展的地方很多

{

chardir[_POSIX_PATH_MAX],stat[4096];

sprintf(dir,"/proc/%s/stat",name);

FILE*fp=fopen(dir,"r");

fgets(stat,4096,fp);

sscanf(stat,"%d",&(pinfo->pid));

char*s,*t;

s=strchr(stat,'(')+1;

t=strchr(stat,')');

strncpy(pinfo->exName,s,t-s);

pinfo->exName[t-s]='\0';

sscanf(t + 2, "%c %d %d %d %d %d %u %u %u %u %u %d %d %d %d %d %d %u%u %d %u %u %u %u %u %u %u %u %d %d %d %d %u",

/* 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*/

&(pinfo->state),

&(pinfo->ppid),

&(pinfo->pgrp),

&(pinfo->session),

&(pinfo->tty),

&(pinfo->tpgid),

&(pinfo->flags),

&(pinfo->minflt),

&(pinfo->cminflt),

&(pinfo->majflt),

&(pinfo->cmajflt),

&(pinfo->utime),

&(pinfo->stime),

&(pinfo->cutime),

&(pinfo->cstime),

&(pinfo->counter),

&(pinfo->priority),

&(pinfo->timeout),

&(pinfo->itrealvalue),

&(pinfo->starttime),

&(pinfo->vsize),

&(pinfo->rss),

&(pinfo->rlim),

&(pinfo->startcode),

&(pinfo->endcode),

&(pinfo->startstack),

&(pinfo->kstkesp),

&(pinfo->kstkeip),

&(pinfo->signal),

&(pinfo->blocked),

&(pinfo->sigignore),

&(pinfo->sigcatch),

&(pinfo->wchan));

}

intcmd_ps()//执行ps指令。遍历/proc目录下的所有文件,对文件夹名为数字的,读取目录下的stat文	//件,解析并输出部分信息

{

printf(" PID TTY TIME CMD\n");

DIR*proc=opendir("/proc");

structdirent *p_dirent;

while((p_dirent=readdir(proc))){

char*name=p_dirent->d_name;

if(digit(name)){

procinfopinfo;

getinfo(name,&pinfo);

charctty[10],ctime[10];

if(pinfo.tty<=1031&&pinfo.tty>1024)

sprintf(ctty,"tty%d",(pinfo.tty-1024));

else

if(pinfo.tty>34816)

sprintf(ctty,"pts/%d",pinfo.tty-34816);

else{

ctty[0]='?';

ctty[1]='\0';

}

sprintf(ctime,"%2d:%2d:%2d",pinfo.utime/360000,(pinfo.utime/6000)%60,(pinfo.utime/100)%60);

printf("%5d%-8s %8s %s\n",pinfo.pid,ctty,ctime,pinfo.exName);

}

}

return0;

}

//<include>部分

//shell.h

#ifndefSHELL

#defineSHELL

#include<stdio.h>

#include<unistd.h>

#include<sys/types.h>

#include<fcntl.h>

#include<dirent.h>

#include<string.h>

#include<linux/sched.h>

#include<errno.h>

#include<pwd.h>

#include"ls.h"

#include"ps.h"

#endif

//ps.h

#ifndefPS_H_INCLUDED

#definePS_H_INCLUDED

typedefstruct statstruct_proc {

int pid; /** The process id. **/

char exName [_POSIX_PATH_MAX]; /** The filename of the executable**/

char state; /** 1 **/ /** R is running, S is sleeping,

D is sleeping in an uninterruptible wait,

Z is zombie, T is traced or stopped **/

unsigned euid, /** effective user id **/

egid; /** effective group id */

int ppid; /** The pid of the parent. **/

int pgrp; /** The pgrp of the process. **/

int session; /** The session id of theprocess. **/

int tty; /** The tty the process uses **/

int tpgid; /** (too long) **/

unsignedint flags; /** The flags of the process. **/

unsignedint minflt; /** The number of minor faults **/

unsignedint cminflt; /** The number of minor faults withchilds **/

unsignedint majflt; /** The number of major faults **/

unsignedint cmajflt; /** The number of major faults withchilds **/

int utime; /** user mode jiffies **/

int stime; /** kernel mode jiffies **/

int cutime; /** user mode jiffies with childs **/

int cstime; /** kernel mode jiffies withchilds **/

int counter; /** process's next timeslice **/

int priority; /** the standard nice value, plusfifteen **/

unsignedint timeout; /** The time in jiffies of the nexttimeout **/

unsignedint itrealvalue; /** The time before the next SIGALRMis sent to the process **/

int starttime; /** 20 **/ /** Time the process startedafter system boot **/

unsignedint vsize; /** Virtual memory size **/

unsignedint rss; /** Resident Set Size **/

unsignedint rlim; /** Current limit in bytes on the rss**/

unsignedint startcode; /** The address above which programtext can run **/

unsignedint endcode; /** The address below which programtext can run **/

unsignedint startstack; /** The address of the start of thestack **/

unsignedint kstkesp; /** The current value of ESP **/

unsignedint kstkeip; /** The current value of EIP **/

int signal; /** The bitmap of pending signals **/

int blocked; /** 30 **/ /** The bitmap of blocked signals**/

int sigignore; /** The bitmap of ignored signals**/

int sigcatch; /** The bitmap of catched signals**/

unsignedint wchan; /** 33 **/ /** (too long) **/

int sched, /** scheduler **/

sched_priority; /** scheduler priority **/

}procinfo;

intcmd_ps();

#endif// PS_H_INCLUDED

//ls.h

#ifndefLS_H_INCLUDED

#defineLS_H_INCLUDED

intcmd_ls(char *dirname,int type);

#endif// LS_H_INCLUDED
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: