因此,我正在尝试为我的学校项目创建一个自定义的shell。我的方法是创建子进程,并让该进程使用我的教授在课堂上简要提到的execvp()函数执行命令。这是我的代码,一如既往,任何帮助都是非常感谢的。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define MAX_LINE 80
int main(int argc, char *argv[])
{
char *input = (char*)malloc(MAX_LINE*sizeof(char));
int should_run = 1;
while(should_run){
printf("osh>");
fflush(stdout);
pid_t pid;
pid = fork();
if(pid < 0){
printf("error with creating chiled process");
return 0;
}
if(pid == 0){
fgets(input, MAX_LINE, stdin);
char *token = strtok(input," ");
if(execvp(token[0], token) < 0){
printf("Error in execution.");
return(0);
}
//should_run = 0;
}
waitpid(pid, 1, 0);
}
return 0;
}发布于 2018-03-06 10:57:11
execvp的原型是
int execvp(const char *file, char *const argv[]);它需要一个指向char的指针作为第一个参数,以及一个指向char*数组的NULL-terminated指针。您传递的是完全错误的参数。
您将传递一个char作为第一个参数,传递一个char*作为第二个参数。
请改用execlp:
int execlp(const char *file, const char *arg, ...
/* (char *) NULL */);所以
char *token = strtok(input," \n");
if(token == NULL)
{
fprintf(stderr, "only delimiters in line\n");
exit(1);
}
if(execlp(token, token, NULL) < 0){
fprintf(stderr, "Error in execution: %s\n", strerror(errno));
exit(1);
}此外,UNIX中的约定是将错误消息打印到stderr,出现错误的进程的退出状态应该不是0。
发布于 2018-03-06 18:31:36
正如巴勃罗所说,您正在向execvp()传递错误的参数。您可以考虑自己编写一个函数(char **strsplit(char *str, char delim)),该函数接受一个字符串并将其拆分成更小的片段,返回一个字符串数组。
另外,不要忽视编译器的警告,它们会告诉你很多事情,我建议你用gcc -Wall -Wextra -Werror编译,这样你的程序中几乎所有可能的错误都会被发现。
我之所以告诉你这一点,是因为waitpid()将指向整数的指针作为第二个参数,以获取派生程序的状态更新。有了这个状态,你就可以知道程序是如何退出的(正常,segf,总线错误...),如果出了问题,你可以用它来打印一个错误。
你可以考虑使用execv() (我知道我离题了,但是你可以从中学到有用的东西),然后自己找到正确的可执行文件。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#define MAX_LINE 255
char **strsplit(char *str, char delim);
char *strjoin(char const *s1, char const *s2);
int isexec(char *path)
{
struct stat buf;
lstat(path, &buf);
if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode))
return (1);
return (0);
}
static char *find_exec_readdir(char *paths, char *cmd)
{
DIR *dir;
struct dirent *dirent;
char *exec;
exec = NULL;
if ((dir = opendir(paths)) != NULL)
{
while ((dirent = readdir(dir)) != NULL)
{
if (!strcmp(dirent->d_name, cmd))
{
exec = strdup(dirent->d_name);
break ;
}
}
if (closedir(dir))
dprintf(2, "Failed closing dir.\n");
}
return (exec);
}
char *find_exec(char *cmd, char **paths)
{
char *exec;
char *path;
char *tmp;
int i;
i = -1;
exec = NULL;
path = NULL;
if ((cmd[0] == '.' || cmd[0] == '/'))
{
if (isexec(cmd))
return (strdup(cmd));
return (NULL);
}
while (paths[++i])
if ((exec = find_exec_readdir(paths[i], cmd)) != NULL)
{
tmp = strjoin(paths[i], "/");
path = strjoin(tmp, exec);
free(tmp);
free(exec);
break ;
}
return (path);
}
int handle_return_status(int status)
{
int sig;
int i;
if (!WIFEXITED(status) && WIFSIGNALED(status))
{
sig = WTERMSIG(status);
i = -1;
while (++i <= 13)
{
if (print_signal_error(sig))
{
return (-1);
}
}
dprintf(2, "Process terminated with unknown signal: %d\n", sig, NULL);
return (-1);
}
return (0);
}
int main(int argc, char *argv[])
{
char *input = NULL;
char **command = NULL;
int should_run = 1;
int status = 0;
(void)argc;
(void)argv;
if ((input = (char*)malloc(MAX_LINE*sizeof(char))) == NULL)
return (dprintf(2, "Failed to malloc, abort.\n"));
while(should_run){
printf("osh> ");
fflush(stdout);
pid_t pid;
pid = fork();
if(pid < 0)
return (dprintf(2, "error with creating chiled process\n"));
if(pid == 0){
fgets(input, MAX_LINE, stdin);
command = strsplit(input, ' ');
command[0] = find_exec(command[0], strsplit(getenv("PATH"), ':'));
if(execv(command[0], &command[1]) < 0)
return (dprintf(2, "Error in execution.\n"));
//should_run = 0;
}
waitpid(pid, &status, 0);
handle_ret_status(status);
}
return 0;
}https://stackoverflow.com/questions/49122665
复制相似问题