📄 shell.c
字号:
FILE * fd; int c; if (out) { fd=fopen(name,"r"); if (fd) { while ((c=fgetc(fd))!=EOF) fputc(c,out); fclose(fd); }; }; }void write_file(char * name,char * content) { FILE * fd; fd=fopen(name,"w"); if (fd) { fwrite(content,1,strlen(content),fd); fclose(fd); }; }void init_issue(void) { static char issue_inited=FALSE; struct stat buf; if (issue_inited) return; issue_inited=TRUE; getpwnam("root"); /* dummy call to init /etc dir */ if (stat("/etc/issue",&buf)) write_file("/etc/issue", "Welcome to @V\\n" "Login into @S(@L)\\n"); if (stat("/etc/issue.net",&buf)) write_file("/etc/issue.net", "Welcome to %v\n" "running on %m\n");}int shell_login(FILE * in,FILE * out) { FILE * fd; int c; time_t t; int times; char name[128]; char pass[128]; struct passwd * passwd; init_issue(); setuid(0); setgid(0); rtems_current_user_env->euid= rtems_current_user_env->egid=0; if (out) { if((current_shell_env->devname[5]!='p')|| (current_shell_env->devname[6]!='t')|| (current_shell_env->devname[7]!='y')) { fd=fopen("/etc/issue","r"); if (fd) { while ((c=fgetc(fd))!=EOF) { if (c=='@') { switch(c=fgetc(fd)) { case 'L':fprintf(out,"%s",current_shell_env->devname); break; case 'B':fprintf(out,"0"); break; case 'T': case 'D':time(&t); fprintf(out,"%s",ctime(&t)); break; case 'S':fprintf(out,"RTEMS"); break; case 'V':fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice); break; case '@':fprintf(out,"@"); break; default :fprintf(out,"@%c",c); break; }; } else if (c=='\\') { switch(c=fgetc(fd)) { case '\\':fprintf(out,"\\"); break; case 'b':fprintf(out,"\b"); break; case 'f':fprintf(out,"\f"); break; case 'n':fprintf(out,"\n"); break; case 'r':fprintf(out,"\r"); break; case 's':fprintf(out," "); break; case 't':fprintf(out,"\t"); break; case '@':fprintf(out,"@"); break; }; } else { fputc(c,out); }; }; fclose(fd); } } else { fd=fopen("/etc/issue.net","r"); if (fd) { while ((c=fgetc(fd))!=EOF) { if (c=='%') { switch(c=fgetc(fd)) { case 't':fprintf(out,"%s",current_shell_env->devname); break; case 'h':fprintf(out,"0"); break; case 'D':fprintf(out," "); break; case 'd':time(&t); fprintf(out,"%s",ctime(&t)); break; case 's':fprintf(out,"RTEMS"); break; case 'm':fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")"); break; case 'r':fprintf(out,_RTEMS_version); break; case 'v':fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice); break; case '%':fprintf(out,"%%"); break; default :fprintf(out,"%%%c",c); break; }; } else { fputc(c,out); }; }; fclose(fd); } }; }; times=0; strcpy(name,""); strcpy(pass,""); for (;;) { times++; if (times>3) break; if (out) fprintf(out,"\nlogin: "); if (!shell_scanline(name,sizeof(name),in,out )) break; if (out) fprintf(out,"Password: "); if (!shell_scanline(pass,sizeof(pass),in,NULL)) break; if (out) fprintf(out,"\n"); if ((passwd=getpwnam(name))) { if (strcmp(passwd->pw_passwd,"!")) { /* valid user */ setuid(passwd->pw_uid); setgid(passwd->pw_gid); rtems_current_user_env->euid= rtems_current_user_env->egid=0; chown(current_shell_env->devname,passwd->pw_uid,0); rtems_current_user_env->euid=passwd->pw_uid; rtems_current_user_env->egid=passwd->pw_gid; if (!strcmp(passwd->pw_passwd,"*")) { /* /etc/shadow */ return 0; } else { /* crypt() */ return 0; }; }; }; if (out) fprintf(out,"Login incorrect\n"); strcpy(name,""); strcpy(pass,""); }; return -1;}rtems_task shell_shell(rtems_task_argument task_argument) { shell_env_t * shell_env =(shell_env_t*) task_argument; shell_cmd_t * shell_cmd; rtems_status_code sc; struct termios term; char * devname; char curdir[256]; char cmd[256]; char last_cmd[256]; /* to repeat 'r' */ int argc; char * argv[128]; sc=rtems_task_variable_add(RTEMS_SELF,(void*)¤t_shell_env,free); if (sc!=RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_task_variable_add(current_shell_env):"); rtems_task_delete(RTEMS_SELF); }; current_shell_env=shell_env; sc=rtems_libio_set_private_env(); if (sc!=RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_libio_set_private_env():"); rtems_task_delete(RTEMS_SELF); }; devname=shell_env->devname; setuid(0); setgid(0); rtems_current_user_env->euid= rtems_current_user_env->egid=0; stdin =fopen(devname,"r+"); if (!stdin) { fprintf(stderr,"shell:unable to open stdin.%s:%s\n",devname,strerror(errno)); rtems_task_delete(RTEMS_SELF); }; setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/ /* make a raw terminal,Linux MANuals */ if (tcgetattr (fileno(stdin), &term)>=0) { term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); term.c_oflag &= ~OPOST; term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */ term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); term.c_cflag = CLOCAL | CREAD |(shell_env->tcflag); term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) { fprintf(stderr,"shell:cannot set terminal attributes(%s)\n",devname); }; stdout=fopen(devname,"r+"); if (!stdout) { fprintf(stderr,"shell:unable to open stdout.%s:%s\n",devname,strerror(errno)); }; setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/ stderr=fopen(devname,"r+"); if (!stderr) { printf("shell:unable to open stderr.%s:%s\n",devname,strerror(errno)); }; /* when the future user environment runs ok * a freopen() reopens the terminals. Now this don't work * (sorry but you can't use because FILENO_STDIN!=0. Better fileno(stdin)) */ }; shell_add_cmd(NULL,NULL,NULL,NULL); /* init the chain list*/ do { /* Set again root user and root filesystem, side effect of set_priv..*/ sc=rtems_libio_set_private_env(); if (sc!=RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_libio_set_private_env():"); rtems_task_delete(RTEMS_SELF); }; if (!shell_login(stdin,stdout)) { cat_file(stdout,"/etc/motd"); strcpy(last_cmd,""); strcpy(cmd,""); printf("\n" "RTEMS SHELL (Ver.1.0-FRC):%s. "__DATE__". 'help' to list commands.\n",devname); chdir("/"); /* XXX: chdir to getpwent homedir */ shell_env->exit_shell=FALSE; for (;;) { /* Prompt section */ /* XXX: show_prompt user adjustable */ getcwd(curdir,sizeof(curdir)); printf("%s [%s] %c ",shell_env->taskname,curdir,geteuid()?'$':'#'); /* getcmd section */ if (!shell_scanline(cmd,sizeof(cmd),stdin,stdout)) break; /*EOF*/ /* evaluate cmd section */ if (!strcmp(cmd,"e")) { /* edit last command */ strcpy(cmd,last_cmd); continue; } else if (!strcmp(cmd,"r")) { /* repeat last command */ strcpy(cmd,last_cmd); } else if (strcmp(cmd,"")) { /* only for get a new prompt */ strcpy(last_cmd,cmd); }; /* exec cmd section */ /* TODO: * To avoid user crash catch the signals. * Open a new stdio files with posibility of redirection * * Run in a new shell task background. (unix &) * Resuming. A little bash. */ if (shell_make_args(cmd,&argc,argv)) { if ((shell_cmd=shell_lookup_cmd(argv[0]))!=NULL) { shell_env->errorlevel=shell_cmd->command(argc,argv); } else { printf("shell:%s command not found\n",argv[0]); shell_env->errorlevel=-1; }; }; /* end exec cmd section */ if (shell_env->exit_shell) break; cmd[0]=0; }; printf("\nGoodbye from RTEMS SHELL :-(\n"); }; } while (shell_env->forever); fclose(stdin ); fclose(stdout); fclose(stderr); rtems_task_delete(RTEMS_SELF);}/* ----------------------------------------------- */rtems_status_code shell_init (char * task_name, rtems_unsigned32 task_stacksize, rtems_task_priority task_priority, char * devname, tcflag_t tcflag, int forever) { rtems_id task_id; rtems_status_code sc; shell_env_t * shell_env; sc=rtems_task_create(new_rtems_name(task_name), task_priority, task_stacksize?task_stacksize:RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES, RTEMS_LOCAL | RTEMS_FLOATING_POINT, &task_id); if (sc!=RTEMS_SUCCESSFUL) { rtems_error(sc,"creating task %s in shell_init()",task_name); return sc; }; shell_env=malloc(sizeof(shell_env_t)); if (!shell_env) { rtems_task_delete(task_id); sc=RTEMS_NO_MEMORY; rtems_error(sc,"allocating shell_env %s in shell_init()",task_name); return sc; }; if (global_shell_env.magic!=new_rtems_name("SENV")) { global_shell_env.magic =new_rtems_name("SENV"); global_shell_env.devname ="/dev/console"; global_shell_env.taskname ="GLOBAL"; global_shell_env.tcflag =0; global_shell_env.exit_shell=0; global_shell_env.forever =TRUE; }; shell_env->magic =global_shell_env.magic; shell_env->devname =devname; shell_env->taskname =task_name; shell_env->tcflag =tcflag; shell_env->exit_shell=FALSE; shell_env->forever =forever; return rtems_task_start(task_id,shell_shell,(rtems_task_argument) shell_env);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -