当前位置: 首页 > news >正文

wordpress 伪链接昭通seo

wordpress 伪链接,昭通seo,济宁有做企业网站吗,网站维护报价表目录 一、模块框架图 二、实现目标 三、实现原理 四、全局变量 五、环境变量函数 六、初始化环境变量表函数 七、输出命令行提示符模块 八、提取命令输入模块 九、填充命令行参数表模块 十、检测并处理内建命令模块 十一、执行命令模块 十二、源码 一、模块框架图…

目录

一、模块框架图

二、实现目标

三、实现原理

四、全局变量 

五、环境变量函数 

六、初始化环境变量表函数

七、输出命令行提示符模块

八、提取命令输入模块

九、填充命令行参数表模块

十、检测并处理内建命令模块

十一、执行命令模块

十二、源码


一、模块框架图

二、实现目标

  • 要能处理普通命令
  • 要能处理内建命令
  • 要能帮助我们理解内建命令/本地变量/环境变量这些概念
  • 要能帮助我们理解shell的允许原理

三、实现原理

# 考虑下面这个与shell典型的互动:

[root@localhost epoll]# lsclient.cpp  readme.md  server.cpp  utility.h[root@localhost epoll]# psPID TTY          
TIME CMD3451 pts/0    
3514 pts/0    
00:00:00 bash00:00:00 ps

# ⽤下图的时间轴来表⽰事件的发⽣次序。其中时间从左向右。shell由标识为sh的⽅块代表,它随着时间的流逝从左向右移动。shell从⽤⼾读⼊字符串"ls"。shell建⽴⼀个新的进程,然后在那个进程中运⾏ls程序并等待那个进程结束。

# 然后shell读取新的⼀⾏输⼊,建⽴⼀个新的进程,在这个进程中运⾏程序 并等待这个进程结束。

四、全局变量 

  • 我们的shell内部有两张表命令行参数表和环境变量表
  • 同时我们还要定义一张哈希表方便处理别名
  • 定义两个数组用来方便处理记录路径
  • lastcode记录上一次的进程退出码、
  • 宏定义大小方便开辟数组 以及命令行输出格式
#define COMMAND_SIZE 1024
#define FORMAT "[%s@%s %s]# "// 下面是shell定义的全局数据// 1. 命令行参数表
#define MAXARGC 128
char* g_argv[MAXARGC];
int g_argc = 0;// 2. 环境变量表
#define MAX_ENVS 100
char* g_env[MAX_ENVS];
int g_envs = 0;// 3. 别名映射表
std::unordered_map<std::string, std::string> alias_list;// for test
char cwd[1024];
char cwdenv[1024];// last exit code
int lastcode = 0;

五、环境变量函数 

  •  环境标量函数直接调用getenv获取在返回即可
  • 注意GetPWD需要ssnprintf格式化写入即可
  • DirName直接从后面查找分割符\ 然后返回之后的字符串即可
const char* GetUserName()
{const char* name = getenv("USER");return name == NULL ? "None" : name;
}const char* GetHostName()
{const char* hostname = getenv("HOSTNAME");return hostname == NULL ? "None" : hostname;
}const char* GetPwd()
{//const char *pwd = getenv("PWD");const char* pwd = getcwd(cwd, sizeof(cwd));if (pwd != NULL){snprintf(cwdenv, sizeof(cwdenv), "PWD=%s", cwd);putenv(cwdenv);}return pwd == NULL ? "None" : pwd;
}const char* GetHome()
{const char* home = getenv("HOME");return home == NULL ? "" : home;
}
string DirName(const char* pwd)
{
#define SEP "/"string ret = pwd;int index = ret.rfind(SEP);if (ret == SEP){return SEP;}if (index == string::npos){return "BUG?";}string t = ret.substr(index+1);return t;
}

六、初始化环境变量表函数

  • 直接把enriron指向的环境变量表拷贝到我们的环境变量表里面 为了区分我们的shell和系统的我们在末尾添加上haha区分
  • 再让environ指向我们的环境变量表即可。
void InitEnv()
{extern char** environ;memset(g_env, 0, sizeof(g_env));g_envs = 0;for (int i = 0; environ[i]; i++){g_env[i] = (char*)malloc(strlen(environ[i]) + 1);strcpy(g_env[i], environ[i]);g_envs++;}g_env[g_envs++] = "haha";g_env[g_envs] = NULL;for (int i = 0; g_env[i]; i++){putenv(g_env[i]);cout << g_env[i] << endl;}environ = g_env;
}

七、输出命令行提示符模块

  • 先定义一个字符输出存储命令行提示符
  • 然后snprintf格式化写入字符数组中 在输出即可。
void PrintCommandPrompt()
{char cmd_prompt[COMMAND_SIZE];MakeCommandLine(cmd_prompt, sizeof(cmd_prompt));std::cout << cmd_prompt;
}
void MakeCommandLine(char cmd_prompt[], int size)
{snprintf(cmd_prompt, size, FORMAT, GetUserName(), GetHostName(), DirName(GetPwd()).c_str());
}
const char* GetUserName()
{const char* name = getenv("USER");return name == NULL ? "None" : name;
}const char* GetHostName()
{const char* hostname = getenv("HOSTNAME");return hostname == NULL ? "None" : hostname;
}const char* GetPwd()
{//const char *pwd = getenv("PWD");const char* pwd = getcwd(cwd, sizeof(cwd));if (pwd != NULL){snprintf(cwdenv, sizeof(cwdenv), "PWD=%s", cwd);putenv(cwdenv);}return pwd == NULL ? "None" : pwd;
}const char* GetHome()
{const char* home = getenv("HOME");return home == NULL ? "" : home;
}
string DirName(const char* pwd)
{
#define SEP "/"string ret = pwd;int index = ret.rfind(SEP);if (ret == SEP){return SEP;}if (index == string::npos){return "BUG?";}string t = ret.substr(index+1);return t;
}

八、提取命令输入模块

  • 这里先fgets获取标准输入到字符数组中
  • 然后构造字符串删除erase\0 然后去map中判断是否为别名
  • 如果是直接把value的值拷贝到数组中即可 然后return ture退出
  • 不是别名则把用户回车的\n字符消除 同时如果用户只回车此时n==0
  • 不做处理返回false 其他返回true;
bool GetCommandLine(char* commandline, int size)
{const char* ret=fgets(commandline, size, stdin);if (ret == NULL){return false;}std::string a = ret;a.erase(a.size() - 1, 1);if (alias_list.count(a)){strcpy(commandline, alias_list[a].c_str());return true;}int n = strlen(commandline);commandline[n - 1] = 0;if (n == 0){return false;}return true;
}

九、填充命令行参数表模块

  • 先strtok获取指向第一个空格字符串
  • while的那个ret不为空时填充g_argv参数表
  • 继续分割填充,直到找不到空格,说明字符串分割完毕
  • 最后填充在g_argv表最后填充NULL即可
  • 根据g_argv大小判断是否填充成功 成功返回ture 反之返回flase 
bool CommandParse(char* commandline)
{
#define SEP " "g_argc = 0;char* ret = strtok(commandline, SEP);if (ret == NULL){return false;}while (ret){g_argv[g_argc++] = ret;ret = strtok(nullptr, SEP);}g_argv[g_argc] = ret;for (int i = 0; g_argv[i]; i++){cout << g_argv[i] << " ";}cout << endl;return g_argc > 0 ? true : false;
}

十、检测并处理内建命令模块

# 先根据g_argv表的第一个命令 判断分流检测处理

  • cd命令如果只有cd 那就直接获取家目录的环境变量字符串
  • chdir修改当前命令为家目录即可
  • 否则直接chdir修改当前目录的路径为g_argv[1]
  • echo命令判断分流
  • echo $?直接返回lastcode退出码 再设置wield0即可
  • echo $xxx 直接获取xxx的环境变量 再输出即可
  • echo xxx 直接打印xxx字符串g_argv[1]即可
  • export命令先判断是否填写了要导入的环境变量
  • 没有直接返回ture不做处理 否则直接putenv导入g_argv[1]环境变量即可
  • alias命令 这里只处理不带命令选项的替换
  • strtok分割=前后字符串然后 存储到map中即可

bool CheckAndExecBuiltion()
{std::string t = g_argv[0];if (t == "cd"){return Cd();}else if (t == "echo"){return Echo();}else if (t == "export"){return Export();}else if (t == "alias"){cout << "开始替换" << endl;return Alias();}else{return false;}
}
bool Cd()
{std::string t;if (g_argc == 1){t = GetHome();if (t == ""){return true;}chdir(t.c_str());}else{t =g_argv[1];chdir(t.c_str());}return true;
}
bool Echo()
{std::string t = g_argv[1];if (t=="$?"){std::cout << lastcode << std::endl;lastcode = 0;}else if (t[0] == '$'){char* ret = getenv(t.substr(1).c_str());if (ret){cout << ret << endl;}}else{cout << t << endl;}return true;
}
bool Export()
{if (g_argc != 2){return true;}putenv(g_argv[1]);return true;
}
bool Alias()
{
#define SEP "="char* t = g_argv[1];char* ret = strtok(t, SEP);if (ret == NULL){return false;}string a=std::string(ret),b = std::string(strtok(NULL, SEP));alias_list[a] = b;cout << alias_list[a] <<" "<<alias_list.count(a)<<endl;cout << a<< "->" << b << endl;return true;
}

十一、执行命令模块

  • 直接创建子进程,子进程通过execvp程序替换执行命令,执行完后exit退出
  • 然后父进程waitpid等待子进程,同时把lastcode更新即可
int Execute()
{pid_t id = fork();if (id == 0){execvp(g_argv[0], g_argv);exit(1);}int status = 0;pid_t rid=waitpid(id, &status, 0);if (rid > 0){lastcode = WEXITSTATUS(status);}return 0;
}

    十二、源码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<unistd.h>
    #include<sys/types.h>
    #include<sys/wait.h>
    #include<unordered_map>#define COMMAND_SIZE 1024
    #define FORMAT "[%s@%s:%s]# "// 下面是shell定义的全局数据//1. 命令行参数表
    #define MAXARGC 128
    char *g_argv[MAXARGC]; 
    int g_argc = 0;//2. 环境变量表
    #define MAX_ENVS 100
    char* g_env[MAX_ENVS];
    int g_envs = 0;//3. 别名映射表
    std::unordered_map<std::string, std::string> alias_list;// for test
    char cwd[1024];
    char cwdenv[1024];// last exit code
    int lastcode = 0;//获取用户名
    const char *GetUserName()
    {const char *name = getenv("USER");return name == NULL ? "None" : name;
    }//获取主机名
    const char *GetHostName()
    {const char *hostname = getenv("HOSTNAME");return hostname == NULL ? "None" : hostname;
    }//获取当前路径
    const char *GetPwd()
    {//const char *pwd = getenv("PWD");const char *pwd = getcwd(cwd, sizeof(cwd));if(pwd != NULL){snprintf(cwdenv, sizeof(cwdenv), "PWD=%s", cwd);putenv(cwdenv);}return pwd == NULL ? "None" : pwd;
    }//获取家目录
    const char *GetHome()
    {const char *home = getenv("HOME");return home == NULL ? "" : home;
    }//初始化环境变量
    void InitEnv()
    {extern char **environ;memset(g_env, 0, sizeof(g_env));g_envs = 0;//本来要从配置文件中来//1. 获取环境变量for (int i = 0; environ[i]; i++){// 1.1 申请空间g_env[i] = (char*)malloc(strlen(environ[i]) + 1);strcpy(g_env[i], environ[i]);g_envs++;}g_env[g_envs++] = (char*)"HAHA=for_test"; //for_testg_env[g_envs] = NULL;//2. 导成环境变量for (int i = 0; g_env[i]; i++){putenv(g_env[i]);std::cout << g_env[i] << std::endl;}environ = g_env;
    }//command
    bool Cd()
    {if(g_argc == 1){std::string home = GetHome();if(home.empty()) return true;chdir(home.c_str());}else{std::string where = g_argv[1];// cd - / cd ~if(where == "-"){// Todo}else if(where == "~"){// Todo}else{chdir(where.c_str());}}return true;
    }void Echo()
    {if(g_argc == 2){// echo "hello tata"// echo $?// echo $PATHstd::string opt = g_argv[1];if(opt == "$?"){std::cout << lastcode << std::endl;lastcode = 0;}else if(opt[0] == '$'){std::string env_name = opt.substr(1);const char *env_value = getenv(env_name.c_str());if(env_value)std::cout << env_value << std::endl;			}else{std::cout << opt << std::endl;}}
    }bool Export()
    {if (g_argc != 2){return false;}putenv(g_argv[1]);return true;
    }bool Alias()
    {char* t = g_argv[1];char* ret = strtok(t, "=");if (ret == NULL){return false;}string a=std::string(ret),b = std::string(strtok(NULL, "="));alias_list[a] = b;std::cout << alias_list[a] << " " << alias_list.count(a) << std::endl;std::cout << a << "->" << b << std::endl;return true;
    }//绝对路径改为目录名
    std::string Dirname(const char *pwd)
    {
    #define SLASH "/"std::string dir = pwd;if(dir == SLASH) return SLASH;auto pos = dir.rfind(SLASH);if(pos == std::string::npos) return "BUG?";return dir.substr(pos+1); // +1是为了去掉目录名前面的/
    }//制作命令行提示符
    void MakeCommandLine(char cmd_prompt[], int size)
    {snprintf(cmd_prompt, size, FORMAT, GetUserName(), GetHostName(), Dirname(GetPwd()).c_str());
    }//打印命令行提示符
    void PrintCommand()
    {char prompt[COMMAND_SIZE];MakeCommandLine(prompt, sizeof(prompt));printf("%s", prompt);fflush(stdout);
    }//判断输入内容
    bool GetCommandLine(char *out, int size)
    {//scanf()是以空格作为分隔符的,但是我们的命令是一整个字符串//ls -a -l => "ls -a -l\n”字符串char *c = fgets(out, size, stdin);if(c == NULL) return false;out[strlen(out)-1] = 0; // 清理\nif(strlen(out) == 0) return false;return true;
    }//命令行分析 "ls -a -l" => "ls" "-a" "-l"
    bool CommandParse(char *commandline)
    {
    #define SEP " " //分隔符g_argc = 0;g_argv[g_argc++] = strtok(commandline, SEP);while((bool)(g_argv[g_argc++] = strtok(nullptr, SEP)));g_argc--; // NULL不算,去掉return g_argc > 0 ? true:false;
    }//测试命令行参数分割,打印
    void PrintArgv()
    {for(int i = 0; g_argv[i]; i++){printf("argv[%d]->%s\n", i, g_argv[i]);}printf("g_argc:%d\n", g_argc);
    }//处理并执行内建命令
    bool CheckAndExcuteBuiltn()
    {std::string cmd = g_argv[0];if(cmd == "cd"){Cd();return true;}else if(cmd == "echo"){Echo();return true;}else if(cmd == "export"){Export();return true;}else if(cmd == "alias"){std::cout << "开始替换" << std::endl;return Alias();}elsereturn false;
    }//执行命令
    int Execute()
    {pid_t id = fork();if(id == 0){//childexecvp(g_argv[0], g_argv);exit(1);}int status = 0;//fathepid_t rid = waitpid(id, &status, 0);if(rid > 0){lastcode = WEXITSTATUS(status);}return 0;
    }int main()
    {// shell启动的时候需要从系统中获取环境变量// 我们的环境变量信息应该从父shell统一来InitEnv();while(true)//持续运行{// 1. 输出命令行提示符PrintCommand();// 2. 获取用户输入的命令char commandline[COMMAND_SIZE];if(!GetCommandLine(commandline, sizeof(commandline)))continue;//什么都没输入直接回车,继续运行printf("echo %s\n", commandline);// 3. 命令行分析 "ls -a -l" => "ls" "-a" "-l"if(!CommandParse(commandline))continue;//PrintArgv(); //测试// 4. 检测并处理内建命令if(CheckAndExcuteBuiltn())continue;// 5. 执行命令Execute();}// ClearUp();return 0;
    }

    http://www.dtcms.com/a/414680.html

    相关文章:

  • 【rabbitmq 高级特性】全面详解RabbitMQ TTL (Time To Live)
  • STM32启动流程全面解析:从上电复位到进入应用程序main函数
  • QQ可以在网站做临时会话么ysl免费网站建设
  • 做网站的女生多么镇江市住房城乡建设局网站
  • 后端两个接口需分开写,前端需不串行并同时刷新调用但数据不同步NOTE
  • 华北建设集团有限公司oa网站上海旅游网站建设情况
  • Appinventor笔记4-数字块与文本块
  • 龙溪营销型网站制作上海官网
  • 支付方式大升级!AI代理将进入购物环节
  • 前端实验(序)——前端开发基础
  • reset saved-configuration 概念及题目
  • 口腔病变识别分割数据集labelme格式1317张1类别
  • 做网站的qq兼职网易企业邮箱登录登录入口
  • 【开题答辩全过程】以 springboot毕业设计管理系统为例,包含答辩的问题和答案
  • 越南网站建设青岛做网络直播的网站
  • 【愚公系列】《人工智能70年》045-生成式Al的辉煌与难题(ChatGPT一鸣惊人)
  • 学习嵌入式的第四十二天——ARM——UART
  • MCP协议深度解析(理论篇):AI工具生态的统一语言
  • 沧州网站建设哪家专业微娱网络小程序代理
  • git-filter-repo - 强大的Git历史重写工具
  • 阿里云wordpress在哪里设置密码网站建设相关优化
  • 常州专业网站建设公司咨询做家具有那个网站好
  • Vim复制粘贴剪切命令详解
  • STM32H743-ARM例程8-EXTI外部中断
  • ARM(IMX6ULL)——通信(UART)
  • 网站 开发逻辑开发app开发公司
  • Kong Gateway 实操实例:代理上游服务并配置限流插件
  • 陕西西安网站设计公司重庆住房建设工程信息网官网
  • 【鸿蒙心迹】 我和新人的鸿蒙应用上架之路
  • 鸿蒙NEXT开发浅进阶到精通14:鸿蒙开发项目中遇到的需求问题及解决笔记05