分隔符和替换最长命令变量的问题

问题描述 投票:0回答:0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAX_COMMAND_LENGTH 510
#define MAX_ARGUMENTS 10

typedef struct {
    char *name;
    char *value;
} CommandVariable;

CommandVariable *command_variables = NULL;
int num_command_variables = 0;
int total_commands = 0;
int total_args = 0;
void add_command_variable(const char *name, const char *value) {
    CommandVariable *new_variable = (CommandVariable *) malloc(sizeof(CommandVariable));
    new_variable->name = strdup(name);
    new_variable->value = strdup(value);
    command_variables = (CommandVariable *) realloc(command_variables, (num_command_variables + 1) * sizeof(CommandVariable));
    command_variables[num_command_variables++] = *new_variable;
    free(new_variable);
}

void replaceSubstring(char *str, const char *oldSubstr, const char *newSubstr) {
    int i, j, k;
    int oldSubstrLen = strlen(oldSubstr);
    int newSubstrLen = strlen(newSubstr);
    int strLen = strlen(str);
    int replaced = 0;

    // Loop through the string
    for (i = 0; i <= strLen - oldSubstrLen && !replaced; ) {
        j = 0;

        // Check if current substring matches oldSubstr
        while (j < oldSubstrLen && str[i + j] == oldSubstr[j]) {
            j++;
        }

        // If oldSubstr is found, replace it with newSubstr
        if (j == oldSubstrLen) {
            // Allocate memory for the new string with enough space for newSubstr
            char *newStr = (char *)malloc((strLen - oldSubstrLen + newSubstrLen + 1) * sizeof(char));
            if (newStr == NULL) {
                // Handle memory allocation error
                printf("Error: Memory allocation failed\n");
                return;
            }

            // Copy the original string up to the replaced substring to newStr
            strncpy(newStr, str, i);
            newStr[i] = '\0'; // Null-terminate the new string

            // Concatenate newSubstr to newStr
            strcat(newStr, newSubstr);

            // Concatenate the rest of the original string after the replaced substring to newStr
            strcat(newStr, str + i + oldSubstrLen);

            // Copy the new string back to the original string
            strcpy(str, newStr);

            // Free memory allocated for newStr
            free(newStr);

            replaced = 1;
        } else {
            // Move the pointer i to the next character
            i++;
        }
    }
}

void execute_command(char *command) {
    char *arguments[MAX_ARGUMENTS + 1]; // extra slot for NULL pointer
    int arg_count = 0;
    char *outer_delim = ";";
    char *inner_delim = " ";
    char *outer_token, *inner_token, *outer_saveptr, *inner_saveptr;

    outer_token = strtok_r(command, outer_delim, &outer_saveptr);

    while (outer_token != NULL) {
        total_commands++;
        char name1[MAX_COMMAND_LENGTH];
        char value1[MAX_COMMAND_LENGTH];
        if (sscanf(outer_token, "%[^=]=%[^\n]", name1, value1) == 2) {
            add_command_variable(name1, value1);
            outer_token = strtok_r(NULL, outer_delim, &outer_saveptr);
            continue;
        }
        char *key = outer_token;
        while((key = strchr(key, '$')) != NULL){
            int i ;
            int j = -1;
            int len = 0;
            for(i =0; i<num_command_variables;i++) {
                char *help = key+1;
                char *str = command_variables[i].name;
                if (strstr(help, str) != NULL || strcmp(help, str) == 0) {
                    //shell> va=emanuel; var=malloul ; echo "$va $var"

                   if (len < strlen(command_variables[i].name)) {
                        len = strlen(command_variables[i].name);
                        j = i;
                    }

                }
            }
                if (j != -1) {
                    char s[strlen(command_variables[j].name) + 3 + 1]; // +1 for null terminator
                    strcpy(s, "$");
                    strcat(s, command_variables[j].name);
                    replaceSubstring(outer_token, s, command_variables[j].value);
                    key = outer_token;


                }
            }

        inner_token = strtok_r(outer_token, inner_delim, &inner_saveptr);
        while (inner_token != NULL) {
            total_args++;
            if(arg_count > MAX_ARGUMENTS){
                printf("Too many arguments\n");
                total_args = total_args - arg_count; //total legal amount of commands and args
                total_commands--;
                outer_token = strtok_r(NULL, outer_delim, &outer_saveptr);
                continue;
            }

            if(inner_token[0]=='"' ){
                char *s = malloc(strlen(inner_token)+1);
                strcpy(s, inner_token+1);
                if(strchr(s,'"')){
                    s[strlen(s)-1] = '\0';
                    arguments[arg_count] = s;
                }else {
                    inner_token = strtok_r(NULL, inner_delim, &inner_saveptr);
                    while (inner_token != NULL) {
                        s = realloc(s, strlen(s) + strlen(inner_token) + 2);
                        strcat(s, " ");
                        strcat(s, inner_token);
                        inner_token = strtok_r(NULL, inner_delim, &inner_saveptr);
                    }
                    s[strlen(s) - 1] = '\0';
                    arguments[arg_count] = s;
                }
            }else {
                arguments[arg_count] = inner_token;
            }
            arg_count++;
            inner_token = strtok_r(NULL, inner_delim, &inner_saveptr);
        }
        if (arg_count > 0) {
            arguments[arg_count] = NULL; // NULL-terminate the argument list
            pid_t pid = fork();
            if (pid < 0) {
                printf("Failed to fork\n");
                return;
            } else if (pid == 0) {
                // child process
                execvp(arguments[0], arguments);
                printf("Failed to execute %s\n", arguments[0]);
                exit(1);
            } else {
                // parent process
                int status;
                waitpid(pid, &status, 0);
            }
        }
        arg_count = 0 ;

        //fork


        outer_token = strtok_r(NULL, outer_delim, &outer_saveptr);
    }
}

int main(){
    char command[MAX_COMMAND_LENGTH + 1];
    int consecutive_enter_count = 0;

    while (consecutive_enter_count < 3) {
        printf("#cmd:%d|#args:%d@current dir> ",total_commands,total_args);
        fflush(stdout); // flush stdout to ensure prompt is displayed

        if (fgets(command, sizeof(command), stdin) == NULL) {
            break; // error reading input
        }

        size_t len = strlen(command);
        if (len == 0) {
            consecutive_enter_count++;
        } else if (command[len - 1] == '\n') {
            command[len - 1] = '\0';
            if (strlen(command) == 0) {
                consecutive_enter_count++;
            }else if (strcmp(command, "cd") == 0) {
                printf("cd is not supported\n");
            } else {
                execute_command(command);
                consecutive_enter_count =0;
            }
        } else {
            // command too long
            printf("Command too long\n");
            while (fgets(command, sizeof(command), stdin) != NULL && command[strlen(command) - 1] != '\n') {
                // flush remaining characters from input buffer
            }
        }

        // check if consecutive enters count has reached 3
        if (consecutive_enter_count == 3) {
            break;
        }
    }
    return 0;
}

发送此命令时

va=emanuel; var=malloul ; echo "$va $var"

预期输出为:

emanuel malloul

我的结果是:

emanuel emanuelr
Failed to execute manuelr

我总结了这个原因:Failed to execute manuelr”是delimeters similarity的问题。

文字背后的原因是:

emanuel emanuelr
是由于行:

if (strstr(help, str) != NULL || strcmp(help, str) == 0) { 

str
var
help
var
时,由于未知原因未输入 if.

我已尽力解决这些问题,但没有成功。如果有人可以提供帮助,我们将不胜感激。

c linux linux-kernel delimiter
© www.soinside.com 2019 - 2024. All rights reserved.