用execl中的变量替换字符串值并停止执行
Replace string value with variable in execl and execution stopping
我正在构建一个类似于 shell 的 linux,我正在尝试执行外部命令,就像在 linux 中一样,开头为“./”。
我是这样读命令的:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include "commands/commands.h"
bool starts_with(const char *a, const char *b){
if(strncmp(a,b,strlen(b)) == 0){
return 1;
}
return 0;
}
int main(int argc, char *argv[]){
char cmd[500];
do{
printf("$ > ");
fgets(cmd, 499, stdin);
if(starts_with(cmd, "./")){
execute_external_command(cmd);
}else{
//execute_interal_command(cmd);
}
}while(strcmp(cmd, "exit\n") != 0);
return 0;
}
这就是我的子进程被新进程替换的方式,一个名为 "hello" 的程序。它只是将 "Hello World" 打印到屏幕上。
else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
//Replace child process with a new process
if(execl("hello", "hello", NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
它工作得很好。但是我想用一个变量替换那个 "hello" ,就像我键入“./hello”从那里获取 "hello" 部分并将其用作 execl() 函数中的变量一样。
我试过这样做,但似乎无法找到 "hello"。我尝试将其打印在屏幕上,它按应有的方式打印 "hello" 。任何想法为什么不执行该过程?
else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
char program[10];
int len = strlen(cmd) - 2;
memcpy(program, &cmd[2],len);
//Replace child process with a new process
if(execl(program, program, NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
第二个问题:在我的第一个执行方法中,它在 execl() 函数中使用 "hello" 作为字符串执行得很好。我总是在屏幕上打印“$ >”字符串,它要求输入。但是当子进程完成他的执行时,整个程序就停止了。如果我愿意,我怎样才能让他再次在屏幕上打印那个“$>”字符串,以便我执行其他命令。提前致谢
更新:执行外部命令的函数
void execute_external_command(char cmd[]){
pid_t pid;
int rv;
int commpipe[2];
//Creting pipe
if(pipe(commpipe)){
fprintf(stderr, "Error creating pipe!!\n");
exit(1);
}
if((pid=fork()) == -1){
fprintf(stderr, "Error forking ew process!\n");
exit(2);
}
if(pid){
//Parent process
dup2(commpipe[1],1);
close(commpipe[0]);
setvbuf(stdout,(char*)NULL,_IONBF,0);
wait(&rv);
fprintf(stderr, "Child exited with a %d value", rv);
}else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
int len = strlen(cmd) - 2;
char program[len];
memcpy(program, &cmd[2],len);
program[len-1] = '[=13=]';
//Replace child process with a new process
if(execl(program, program, NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
fgets
在字符串中包含尾随的换行符。您必须剥离它才能正确调用二进制文件。此外,您的 memcpy 不会将必要的零字节复制为字符串终止符。尝试:
program[len-1] = '[=10=]';
在 memcpy()
之后。
这应该有所帮助。
另请注意:此代码容易出现缓冲区溢出,因为程序固定为 10 个字节,而 cmd 可以更长。
你可以这样做:
int len = strlen(cmd) - 2;
char program[len];
memcpy(program, &cmd[2],len);
program[len-1] = '[=11=]';
以防止这种情况发生。如果你不关心修改cmd,你也可以这样做:
cmd[strlen(cmd)-1] = '[=12=]';
if (execl(cmd+2, cmd+2, NULL) ...
还有一件事:
甚至不需要删除 ./
部分,execl 可以正常工作。
在父进程中:
if(pid){
//Parent process
dup2(commpipe[1],1);
您将进程的标准输出设置为 commppipe。因此,所有后续的 printf 都将尝试写入损坏的管道,因此 SIGPIPE 会终止您的父进程。
我完全不明白为什么你需要这里的 commpipe,我认为你可以完全忽略它。
我正在构建一个类似于 shell 的 linux,我正在尝试执行外部命令,就像在 linux 中一样,开头为“./”。
我是这样读命令的:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include "commands/commands.h"
bool starts_with(const char *a, const char *b){
if(strncmp(a,b,strlen(b)) == 0){
return 1;
}
return 0;
}
int main(int argc, char *argv[]){
char cmd[500];
do{
printf("$ > ");
fgets(cmd, 499, stdin);
if(starts_with(cmd, "./")){
execute_external_command(cmd);
}else{
//execute_interal_command(cmd);
}
}while(strcmp(cmd, "exit\n") != 0);
return 0;
}
这就是我的子进程被新进程替换的方式,一个名为 "hello" 的程序。它只是将 "Hello World" 打印到屏幕上。
else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
//Replace child process with a new process
if(execl("hello", "hello", NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
它工作得很好。但是我想用一个变量替换那个 "hello" ,就像我键入“./hello”从那里获取 "hello" 部分并将其用作 execl() 函数中的变量一样。
我试过这样做,但似乎无法找到 "hello"。我尝试将其打印在屏幕上,它按应有的方式打印 "hello" 。任何想法为什么不执行该过程?
else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
char program[10];
int len = strlen(cmd) - 2;
memcpy(program, &cmd[2],len);
//Replace child process with a new process
if(execl(program, program, NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
第二个问题:在我的第一个执行方法中,它在 execl() 函数中使用 "hello" 作为字符串执行得很好。我总是在屏幕上打印“$ >”字符串,它要求输入。但是当子进程完成他的执行时,整个程序就停止了。如果我愿意,我怎样才能让他再次在屏幕上打印那个“$>”字符串,以便我执行其他命令。提前致谢
更新:执行外部命令的函数
void execute_external_command(char cmd[]){
pid_t pid;
int rv;
int commpipe[2];
//Creting pipe
if(pipe(commpipe)){
fprintf(stderr, "Error creating pipe!!\n");
exit(1);
}
if((pid=fork()) == -1){
fprintf(stderr, "Error forking ew process!\n");
exit(2);
}
if(pid){
//Parent process
dup2(commpipe[1],1);
close(commpipe[0]);
setvbuf(stdout,(char*)NULL,_IONBF,0);
wait(&rv);
fprintf(stderr, "Child exited with a %d value", rv);
}else{
//Child process
dup2(commpipe[0],0);
close(commpipe[1]);
int len = strlen(cmd) - 2;
char program[len];
memcpy(program, &cmd[2],len);
program[len-1] = '[=13=]';
//Replace child process with a new process
if(execl(program, program, NULL) == -1){
fprintf(stderr, "Error executing new process!\n");
exit(3);
}
}
}
fgets
在字符串中包含尾随的换行符。您必须剥离它才能正确调用二进制文件。此外,您的 memcpy 不会将必要的零字节复制为字符串终止符。尝试:
program[len-1] = '[=10=]';
在 memcpy()
之后。
这应该有所帮助。
另请注意:此代码容易出现缓冲区溢出,因为程序固定为 10 个字节,而 cmd 可以更长。 你可以这样做:
int len = strlen(cmd) - 2;
char program[len];
memcpy(program, &cmd[2],len);
program[len-1] = '[=11=]';
以防止这种情况发生。如果你不关心修改cmd,你也可以这样做:
cmd[strlen(cmd)-1] = '[=12=]';
if (execl(cmd+2, cmd+2, NULL) ...
还有一件事:
甚至不需要删除 ./
部分,execl 可以正常工作。
在父进程中:
if(pid){
//Parent process
dup2(commpipe[1],1);
您将进程的标准输出设置为 commppipe。因此,所有后续的 printf 都将尝试写入损坏的管道,因此 SIGPIPE 会终止您的父进程。 我完全不明白为什么你需要这里的 commpipe,我认为你可以完全忽略它。