#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define MAX_HOST_LEN 32 /* 主机名最大长度 */
#define MAX_PATH_LEN 256 /* 路径的最大长度 */
#define MAX_COMMAND_LEN 256 /*命令的最大长度*/
struct job {
char * precmd; /* 转换前的命令*/
char ** formatcmd; /* 转换后的命令*/
};
struct promptinfo {
char * username; /* 当前用户名*/
char * hostname; /* 主机名*/
uid_t userid; /* 当前用户id */
char * pwdname; /* 当前路径名 */
char promptchar; /* '#' 为管理员, '$' 普通用户 */
char * home; /* 主路径 */
}prinfo;
int getprinfo() {
prinfo.userid = getuid();/*得到用户ID*/
/* 得到当前用户名 */
if ( (prinfo.username = getenv("USER")) == NULL) {
perror("getlogin error");
return -1;
}
/* 获得主机名*/
if ( (prinfo.hostname = malloc(MAX_HOST_LEN) ) == NULL) {
perror("malloc hostname error");
return -2;
}
if ( gethostname(prinfo.hostname, MAX_HOST_LEN) != 0) {
perror("get hostname error");
return -2;
}
/* 获得当前路径名*/
if ( (prinfo.pwdname = malloc(MAX_PATH_LEN) ) == NULL) {
perror("malloc pwdname error");
return -3;
}
if ( (prinfo.pwdname = getcwd(prinfo.pwdname, MAX_PATH_LEN)) == NULL) {
perror("get current path error");
return -3;
}
/* 获得命令行提示符 */
if (prinfo.userid < 0) {
printf("getuid error.");
return -4;
}
if (prinfo.userid == 0) {
prinfo.promptchar = '#';
} else {
prinfo.promptchar = '$';
}
/* 获得主路径名*/
if ( (prinfo.home = getenv("HOME")) == NULL) {
perror("get home path error");
return -5;
}
return 0;
}
void prompt() {
printf("\033[00;32m%s\033[00;35m@\033[00;36m%s\033[00;33m:\033[00;34m%s\033[00;31m%c\033[00m ",
prinfo.username,
prinfo.hostname,
prinfo.pwdname,
prinfo.promptchar);
}
char ** parseCommand(char * precommand, char ** formatcmd) { /*把命令转换成字符串数组 */
char c;
int count = 0,i = 0,j = 0;
if ( (formatcmd = malloc(sizeof(char*))) == NULL) {
perror("malloc to formatcmd error");
return NULL;
}
if ( (formatcmd[0] = malloc( (strlen(precommand) + 1) * (sizeof(char) ) ) ) == NULL) {
perror("malloc to formatcmd[0] error");
return NULL;
}
while ((c = precommand[i]) == 32) {
i++;
} /* 忽略命令前面的空格*/
while (i < strlen(precommand)) {
c = precommand[i];
if (c == 32) {
while ((c = precommand[i]) == 32) {
i++;
}
formatcmd[count][j] = '\0';
count++;
formatcmd = realloc(formatcmd, count);
if ( (formatcmd[count] = malloc(sizeof(char) * (strlen(precommand) - i + 1) )) == NULL) {
fprintf(stderr,
"malloc formatcmd[%d] error %d: %s",
count,
errno,
strerror(errno));
return NULL;
}
j = 0;
} else {
formatcmd[count][j] = c;
j++;
i++;
}
}
formatcmd[count][j] = '\0';
count++;
formatcmd = realloc(formatcmd, count);
formatcmd[count] = NULL;
return formatcmd;
}
/* main fuction here !!! */
int main(int argc, char * argv[]) {
struct job joba;
char cmdbuf[MAX_COMMAND_LEN];
pid_t child;
int status;
if (getprinfo() < 0) {
printf("getprinfo error\n");
exit(-1);
}
prompt();
while ((fgets(cmdbuf, MAX_COMMAND_LEN, stdin)) != NULL) {
cmdbuf[strlen(cmdbuf) -1] = '\0';/* 以‘\0'结束*/
if (strcmp(cmdbuf, "exit") ==0) {
exit(0);
}
joba.precmd = cmdbuf;
if ((joba.formatcmd = parseCommand(joba.precmd, joba.formatcmd)) != NULL) {
/*如果只输入cd不带参数 直接进入主目录 */
if (strcmp(joba.formatcmd[0], "cd") == 0) {
if (joba.formatcmd[1] == NULL){
joba.formatcmd[1] = prinfo.home;
}
if (chdir(joba.formatcmd[1]) < 0) {
perror("cd");
}
getprinfo();
}
else {
if ((child = fork()) < 0) { /* 创建子进程失败 */
fprintf(stderr,
"fork error %d: %s\n",
errno,
strerror(errno));
}
/* 进入子进程 */
if(child == 0) {
if (execvp(joba.formatcmd[0],
joba.formatcmd) < 0){
perror("exec error");
}
exit(0);
}
/* 等待子进程结束 */
if ((waitpid(child, &status, 0)) < 0) {
perror("waitpid error");
}
}
}
prompt();
}
return 0;
}