我正在尝试将命令从文件中提取到名为char ** commands的变量中;在此变量中,它将保存文件中的所有命令。好吧,如果找到“退出”命令,则该命令必须位于此命令数组的末尾。因此,我尝试像在c ++中一样,通过将bool(在c的情况下为int)设置为整数,然后将其设置为t = 0;只有在其中一个命令中找到单词“ exit”时,我才将其设置为一个。我稍后再添加。问题是在if语句中更改此t变量时出现段错误。
我不确定为什么更改整数变量会给我一个段错误,所以我不太确定从哪里开始。
//
// main.c
// Test
//
// Created by Devin Tripp on 7/17/19.
// Copyright © 2019 Devin Tripp. All rights reserved.
//
/*
Name : Devin Tripp
******************************************************************************
FUNCTIONALITIES IMPLEMENTED-
1. Execute all the External commands (ls, clear, vi etc.)
2. Implement Internal commands: cd, pwd
3. Print Initialize and use environment variables
4. Print environment variables using echo command
5. I/O redirection (<, >)
7. Pipes “|” (multiple) (Ex: ls | grep 'a' | wc)
8.Handle Interrupt Signal: On pressing "Ctrl+C", the command that is running
currently should be terminated, your program should not terminate.
********************************************************************************
*/
#include "Major1.h"
/*GLOBAL VARIABLES*/
int pipes[100][2];
int pipe_count=0, fd, historyIndex = 0;
static char* args[512];
char input_buffer[1024];
char *cmd_exec[100];
int flag, len;
char cwd[1024];
int flag_pipe=1;
pid_t pid;
int no_of_lines;
int environmment_flag;
int flag_pipe, output_redirection, input_redirection;
int pid, status;
char current_directory[1000];
char *input_redirection_file;
char *output_redirection_file;
extern char** environ;
int t;
typedef struct myHistory {
char *data;
} myHistory;
myHistory hist[20];
/***************************Header Files Used*****************************/
void clear_variables(void);
void environmment(void);
void set_environment_variables(void);
void parent_directory(void);
void echo_calling(char *echo_val);
void historyFunc(void);
char* skipcomma(char* str);
static int split(char *cmd_exec, int, int, int);
void pipe_execute(void);
static int command(int, int, int, char *cmd_exec);
void prompt(void);
void sigintHandler(int sigint);
void batchmode(const char *file);
static char* skipwhite(char* s);
/*************************************************************************/
void sigintHandler(int sigint)
{
printf("\n");
signal(SIGINT, sigintHandler);
fflush(stdout);
}
static char* skipwhite(char* s)
{
while (isspace(*s)) ++s;
return s;
}
void clear_variables()
{
t = 0;
fd =0;
flag=0;
len=0;
no_of_lines=0;
pipe_count=0;
flag_pipe=1;
output_redirection=0;
input_redirection=0;
input_buffer[0]='\0';
cwd[0] = '\0';
pid=0;
environmment_flag=0;
int i;
for(i = 0; i < 1024; i++){
input_buffer[i] = '\0';
}
for(i = 0; i < 512; i++){
args[i] = NULL;
}
for(i = 0; i < 100; i++){
cmd_exec[i] = NULL;
}
}
void environmment()
{
int i =1, index=0;
char env_val[1000], *value;
while(args[1][i]!='\0')
{
env_val[index]=args[1][i];
index++;
i++;
}
env_val[index]='\0';
value=getenv(env_val);
if(!value)
printf("\n");
else printf("%s\n", value);
}
void set_environment_variables()
{
int n=1;
char *left_right[100];
if(args[1]==NULL)
{
char** env;
for (env = environ; *env != 0; env++)
{
char* value = *env;
printf("declare -x %s\n", value);
}
return;
}
left_right[0]=strtok(args[1],"=");
while ((left_right[n]=strtok(NULL,"="))!=NULL)
n++;
left_right[n]=NULL;
setenv(left_right[0], left_right[1], 0);
}
void parent_directory()
{
if (getcwd(cwd, sizeof(cwd)) != NULL)
{
printf("%s\n", cwd );
}
else
perror("getcwd() error");
}
void echo_calling(char *echo_val)
{
int i=0, index=0;
environmment_flag=0;
char new_args[1024],env_val[1000], *str[10];
str[0]=strtok(echo_val," ");
str[1]=strtok(NULL, "");
strcpy(env_val, args[1]);
if(str[1]==NULL)
{
printf("\n");
return;
}
if (strchr(str[1], '$'))
{
environmment_flag=1;
}
memset(new_args, '\0', sizeof(new_args));
i=0;
while(str[1][i]!='\0')
{
if(str[1][i]=='"')
{
index=0;
while(str[1][i]!='\0')
{
if(str[1][i]!='"')
{
new_args[index]=str[1][i];
flag=1;
index++;
}
i++;
}
}
else if(str[1][i]==39)
{
index=0;
while(str[1][i]!='\0')
{
if(str[1][i]!=39)
{
new_args[index]=str[1][i];
flag=1;
index++;
}
i++;
}
}
else if(str[1][i]!='"')
{
new_args[index]=str[1][i];
index++;
i++;
}
else i++;
}
new_args[index]='\0';
if((strcmp(args[1], new_args)==0)&&(environmment_flag==0))
printf("%s\n", new_args);
else {
strcpy(args[1], new_args);
if(environmment_flag==1)
{
environmment();
}
else if(environmment_flag==0)
{
printf("%s\n", new_args );
}
}
}
void historyFunc()
{
int i = 0;
while(hist[i].data != NULL){
printf("%s\n", hist[i].data);
i++;
}
}
/*
Changes the string entered into the parameters into an array of strings
EX: "arg1 flag1 flag2 flag3" becomes " "arg1", "flag1", "flag2", "flag3" "
*/
void tokenise_commands(char *com_exec)
{
int i=1;
args[0]=strtok(com_exec," ");
while((args[i]=strtok(NULL," "))!=NULL)
i++;
}
/*
skips the commas on the command
*/
char* skipcomma(char* str)
{
int i=0, j=0;
char temp[1000];
while(str[i++]!='\0')
{
if(str[i-1]!='"')
temp[j++]=str[i-1];
}
temp[j]='\0';
str = strdup(temp);
return str;
}
/*
splits the commands and checks if they equal a built in command.
*/
static int split(char *cmd_exec, int input, int first, int last)
{
char *new_cmd_exec1;
new_cmd_exec1=strdup(cmd_exec);
if(new_cmd_exec1 == NULL) {
} else {
int m=1;
args[0]=strtok(cmd_exec," ");
while((args[m]=strtok(NULL," "))!=NULL)
m++;
args[m]=NULL;
if (args[0] != NULL)
{
if (strcmp(args[0], "exit") == 0)
exit(0);
if (strcmp(args[0], "echo") == 0)
{
cmd_exec = skipcomma(new_cmd_exec1);
int m=1;
args[0]=strtok(cmd_exec," ");
while((args[m]=strtok(NULL," "))!=NULL)
m++;
args[m]=NULL;
}
if(strcmp("cd",args[0])==0)
{
change_directory(args);
return 1;
}
else if(strcmp("pwd",args[0])==0)
{
parent_directory();
return 1;
} else if(strcmp("path", args[0]) == 0){
int i = 2;
char *str = malloc(1024 + sizeof(char*));
while(args[i] != NULL){
strcat(str, args[i]);
i++;
}
print_PATH(args,str);
if(!str)
free(str);
return 1;
}
}
}
return command(input, first, last, new_cmd_exec1);
}
void pipe_execute()
{
int i, n=1, input, first;
input=0;
first= 1;
cmd_exec[0]=strtok(input_buffer,"|");
while ((cmd_exec[n]=strtok(NULL,"|"))!=NULL)
n++;
cmd_exec[n]=NULL;
pipe_count=n-1;
for(i=0; i<n-1; i++)
{
input = split(cmd_exec[i], input, first, 0);
first=0;
}
if(pipe_count == 0){
input=split(cmd_exec[0], input, 1, 1);
} else {
input=split(cmd_exec[i], input, 0, 1);
}
input=0;
return;
}
/*
Create a child process to run a command, create a pipe in case we need one for the commands, we will close it at the bottom anyways if its the last command. This command function will return the input into the next command if there is piping.
*/
static int command(int input, int first, int last, char *cmd_exec)
{
int filedescripter[2], ret, input_fd, output_fd;
ret = pipe(filedescripter);
// temp = tokenise_redirect_input_output(cmd_exec, input_redirection_file, output_redirection_file);
// input_redirection_file = temp[0];
// output_redirection_file = temp[1];
if(ret == -1)
{
perror("pipe");
return 1;
}
pid = fork();
args;
if (pid == 0)
{
if (first==1 && last==0 && input==0)
{
//duplicate the write in to stdin write | read
dup2(filedescripter[1], 1);
close(filedescripter[0]);
close(filedescripter[1]);
}
else if (first==0 && last==0 && input != 0)
{
dup2(input, 0);
dup2(filedescripter[1], 1);
close(filedescripter[0]);
close(filedescripter[1]);
}
else
{
dup2(input, 0);
close(filedescripter[0]);
close(filedescripter[1]);
}
if (strchr(cmd_exec, '<') && strchr(cmd_exec, '>'))
{
input_redirection=1;
output_redirection=1;
char **temp = malloc(512 * sizeof(char*));
temp[0] = malloc(512 * sizeof(char*));
temp[1] = malloc(512 * sizeof(char*));
temp = tokenise_redirect_input_output(cmd_exec, input_redirection_file, output_redirection_file);
input_redirection_file = temp[0];
output_redirection_file = temp[1];
int ln = strlen(input_redirection_file);
input_redirection_file[ln-1] = '\0';
}
else if (strchr(cmd_exec, '<'))
{
input_redirection=1;
input_redirection_file = tokenise_redirect_input(cmd_exec, input_redirection_file);
}
else if (strchr(cmd_exec, '>'))
{
output_redirection=1;
output_redirection_file = tokenise_redirect_output(cmd_exec, output_redirection_file);
}
if(output_redirection == 1)
{
output_fd= creat(output_redirection_file, 0644);
if (output_fd < 0)
{
fprintf(stderr, "Failed to open %s for writing\n", output_redirection_file);
return(EXIT_FAILURE);
}
dup2(output_fd, 1);
close(output_fd);
output_redirection=0;
}
if(input_redirection == 1)
{
input_fd=open(input_redirection_file,O_RDONLY, 0);
if (input_fd < 0)
{
fprintf(stderr, "Failed to open %s for reading\n", input_redirection_file);
return(EXIT_FAILURE);
}
dup2(input_fd, 0);
close(input_fd);
input_redirection=0;
}
if (strcmp(args[0], "export") == 0)
{
set_environment_variables();
return 1;
}
if (strcmp(args[0], "echo") == 0)
{
echo_calling(cmd_exec);
}
else if (strcmp(args[0], "myhistory") == 0)
{
historyFunc();
}
else if(execvp(args[0], args)<0) printf("%s: command not found\n", args[0]);
exit(0);
}
else
{
waitpid(pid, 0, 0);
}
if (last == 1)
close(filedescripter[0]);
if (input != 0)
close(input);
close(filedescripter[1]);
return filedescripter[0];
}
void prompt()
{
printf("Major1Shell> ");
if (getcwd(cwd, sizeof(cwd)) == NULL)
{
perror("getcwd() error");
}
}
void batchmode(const char *file){
//make a file int
// int fd;
char *filename = malloc(sizeof(*file+1));
//open the file
strcpy(filename, file);
char *fileCopy = malloc(1024 * sizeof(char*));
strcpy(fileCopy, file);
/* Pointer to the file */
FILE *fp1;
/* Character variable to read the content of file */
strcpy(fileCopy, current_directory);
strcat(fileCopy, "/");
strcat(fileCopy, filename);
/* Opening a file in r mode*/
fp1= fopen (file, "r");
if(fp1 == NULL){
printf("There was a problem opening the file\n");
} else {
printf("The file %s : was opened successfully\n", filename);
}
char *line = malloc(1025 * sizeof(char*));
char **commands = malloc(512 * sizeof(char*));
int i = 0;
int l = 0;
while(fgets(line, 1024, fp1) != NULL)
{
char *temp;
temp = strtok(line, ";");
while(temp != NULL && strcmp(temp, "\n") != 0 && strcmp(temp, " ")){
temp = skipwhite(temp);
if(strcmp(temp, "exit") == 0){
t = 1;
l = 1;
}
if(t == 1){
//do not add this command
//do not increment i
t = 0; // why am i getting a segfault here
} else {
commands[i] = malloc(512 * sizeof(char*));
strcpy(commands[i], temp);
i++;
}
temp = strtok(NULL, ";");
}
}
if(l == 1){
strcpy(commands[i], "exit");
i++;
commands[i] = NULL;
} else {
commands[i] = NULL;
}
//move the exit command to the back if found
// i = 0;
// while (commands[i] != NULL) {
// if(strcmp(commands[i], "exit") == 0){
// //move this command to the back and move all other commands to the other positions
// }
// }
i = 0;
while(commands[i] != NULL){
printf("Command: %s found\n", commands[i]);
i++;
}
// i = 0;
// while(commands[i] != NULL){
// clear_variables();
// strcpy(input_buffer, commands[i]);
// printf("Command: %s found\n", commands[i]);
// pipe_execute();
// i++;
// }
///print comands for error checking
fclose(fp1);
free(filename);
free(fileCopy);
free(commands);
}
int main(int argc, const char * argv[])
{
if(argc >= 2){
//run shell in batch mode
batchmode(argv[1]);
}
int status;
char ch[2]={"\n"};
getcwd(current_directory, sizeof(current_directory));
signal(SIGINT, sigintHandler);
while (1)
{
clear_variables();
prompt();
fgets(input_buffer, 1024, stdin);
if(strcmp(input_buffer, ch)==0)
{
continue;
}
if(historyIndex >= 20){
historyIndex = 0;
}
hist[historyIndex].data = malloc(512 * sizeof(char*));
strcpy(hist[historyIndex].data, input_buffer);
historyIndex++;
//get the lenth of the string passed in, so that you can put a null character at the end of it.
len = strlen(input_buffer);
input_buffer[len-1]='\0';
if(strcmp(input_buffer, "exit") == 0)
{
flag = 1;
break;
}
pipe_execute();
waitpid(pid,&status,0);
}
if(flag==1)
{
printf("Closing the shell...\n");
exit(0);
return 0;
}
//free all the history data that was allocated
int i = 0;
for(i = 0; i < historyIndex; i++){
free(hist[i].data);
}
return 0;
}
正在读取的文件称为batch.bat,看起来像这样
cd ..; ls -l;
pwd; exit;
ls -l | wc;
我希望程序将所有命令放入一个数组,然后将退出命令放在最后