Получение веб-сервера для локального запуска команд Bash и вывода на веб-страницу - PullRequest
1 голос
/ 03 мая 2019

Я создаю интерактивную веб-страницу, чтобы пользователь мог вводить команду Bash на HTML-странице, нажимать кнопку «Выполнить», и выходные данные будут отображаться на той же странице.

На данный момент мой сервер может работатькоманды, если они помещены в строку поиска, но она не работает для конвейера или флагов, просто основные команды.

Мне нужна помощь, чтобы понять, почему pexec.c ниже не обеспечивает вывод, только пустое значениестр.

**wrc-server.c**

    /*
    ** server.c -- a stream socket server demo
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <sys/wait.h>
    #include <signal.h>
    #include <poll.h>

    #define PORT "3838"  // The port users will be connecting to

    #define BACKLOG 10     // How many pending connections queue will hold

    void sigchld_handler(int s)
    {
        (void)s; // Quiet unused variable warning

        // waitpid() might overwrite errno, so we save and restore it:
        int saved_errno = errno;

        while(waitpid(-1, NULL, WNOHANG) > 0);

        errno = saved_errno;
    }


    // Get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa)
    {
        if (sa->sa_family == AF_INET) {
            return &(((struct sockaddr_in*)sa)->sin_addr);
        }

        return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }

    char *parse(char *command) {
        char * newCommand = (char *) malloc(sizeof(char)*35);
        newCommand = strtok(command, " ");
        newCommand = strtok(NULL, "/ ");

        return newCommand;
    }

    char * execution(char *command) {
        //printf("yo:%s\n", command);

        int piper[2];
        size_t len = 0;
        pipe(piper);
        char* output =  malloc(1000 * sizeof(char));
        memset(output, '\0', 1000* sizeof(char));
        pid_t pid = fork();
        if(pid != 0) // Parent
        {
            wait(NULL);
            close(piper[1]);
            int n = sizeof(output);

            // ----Rob Code
            struct pollfd * poll_fd = malloc(sizeof(struct pollfd));
            poll_fd->fd = piper[0];
            poll_fd->events = POLLIN;

            //wait(NULL);
            //printf("done\n");
            //printf("AAA %s", output);
            if (poll(poll_fd, 1, 0) == 1) { // Pipe data check
                read(piper[0], output, 1000);
            }
            //printf("the command is %s\n", output);
            //read(&output, output, piper[0]);
            //printf("%s\n", piper[0]);
            //dup2(piper[1], 1);
            //close(0)
        }
        else {
            //dup2(piper[1], 1);
            //printf("run: %s", command);

            close(1);
            dup(piper[1]);
            //close(0);
            execlp(command, command, NULL);
            exit(1);
        }
        // dup2 execute and print it out in parent

        // if (*(commands+1) != NULL) // Redirect stdout as long as were not at the last row
        // {
        //     dup2(piper[1], 1);
        //     close(piper[0]);
        // }
        return output;
    }

    int main(void)
    {
        int sockfd, new_fd;  // Listen on sock_fd, new connection on new_fd
        struct addrinfo hints, *servinfo, *p;
        struct sockaddr_storage their_addr; // Connector's address information
        socklen_t sin_size;
        struct sigaction sa;
        int yes = 1;
        char s[INET6_ADDRSTRLEN];
        int rv;

        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE; // use my IP

        if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
            return 1;
        }

        // Loop through all the results and bind to the first we can
        for(p = servinfo; p != NULL; p = p->ai_next) {
            if ((sockfd = socket(p->ai_family, p->ai_socktype,
                 p->ai_protocol)) == -1) {

                perror("server: socket");
                continue;
            }

            if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
                           sizeof(int)) == -1) {

                perror("setsockopt");
                exit(1);
            }

            if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
                close(sockfd);
                perror("server: bind");
                continue;
            }

            break;
        }

        //printf("%s\n", servinfo.ai_canonname);
        freeaddrinfo(servinfo); // All done with this structure

        if (p == NULL)  {
            fprintf(stderr, "server: failed to bind\n");
            exit(1);
        }

        if (listen(sockfd, BACKLOG) == -1) {
            perror("listen");
            exit(1);
        }

        printf("server: waiting for connections...\n");
        int ptds[2];
        char *commands = malloc(sizeof(char)*1212);
        while(1) { // Main accept() loop
            sin_size = sizeof their_addr;
            new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
            if (new_fd == -1) {
                perror("accept");
                continue;
            }

            inet_ntop(their_addr.ss_family,
                      get_in_addr((struct sockaddr *)&their_addr),
                      s, sizeof s);
            printf("server: got connection from %s\n", s);

            char *buf = malloc(1000*sizeof(char));

            memset(buf, '\0', 1000* sizeof(char));

            recv(new_fd, buf, 1000*sizeof(char), 0);
            //printf("%s\n", parse(buf));

            ;

            if (!fork()) { // This is the child process
                close(sockfd); // Child doesn't need the listener

                if (send(new_fd, execution(parse(buf)), 1000, 0) == -1)
                    perror("send");
                close(new_fd);
                exit(0);
            }
            close(new_fd);
        }
        return 0;
    }

**pexec.c**

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <unistd.h>

    #include <sys/types.h>
    #include <sys/wait.h>

    static char* args[512];
    pid_t pid;
    int command_pipe[2];

    #define READ  0
    #define WRITE 1

    static int command(int input, int first, int last)
    {
        int pipettes[2];

        pipe(pipettes);
        pid = fork();

        if (pid == 0) {
            if (first == 1 && last == 0 && input == 0) {
                // First command
                dup2(pipettes[WRITE], STDOUT_FILENO);
            } else if (first == 0 && last == 0 && input != 0) {
                // Middle command
                dup2(input, STDIN_FILENO);
                dup2(pipettes[WRITE], STDOUT_FILENO);
            } else {
                // Last command
                dup2(input, STDIN_FILENO);
            }

            if (execvp( args[0], args) == -1)
                _exit(EXIT_FAILURE);
        }

        if (input != 0)
            close(input);

        close(pipettes[WRITE]);

        if (last == 1)
            close(pipettes[READ]);

        return pipettes[READ];
    }

    static void cleanup(int n)
    {
        int i;
        for (i = 0; i < n; ++i)
            wait(NULL);
    }

    static int run(char* cmd, int input, int first, int last);
    static char line[1024];
    static int n = 0; /* Number of calls to 'command' */

    int main(int argc, char *argv[])
    {
        while (1) {

            //  for(int i = 1; i < argc; i++) {
            //     strcat(line, argv[i]);
            //     strcat(line, " ");
            // }

            /* Read a command line */
            //if (!fgets(line, 1024, stdin))
                //return 0;
            int InputLength = atoi(getenv("INPUT_LENGTH"));
            fread(line, InputLength, 1, stdin);

            int input = 0;
            int first = 1;

            char* cmd = line;
            char* next = strchr(cmd, '@'); /* Find first '|' */

            while (next != NULL) {
                /* 'next' points to '|' */
                *next = '\0';
                input = run(cmd, input, first, 0);

                cmd = next + 1;
                next = strchr(cmd, '@'); /* Find next '|' */
                first = 0;
            }
            input = run(cmd, input, first, 1);
            cleanup(n);
            n = 0;
        }
        return 0;
    }

    static void split(char* cmd);

    static int run(char* cmd, int input, int first, int last)
    {
        split(cmd);
        if (args[0] != NULL) {
            if (strcmp(args[0], "exit") == 0)
                exit(0);
            n += 1;
            return command(input, first, last);
        }
        return 0;
    }

    static char* skipwhite(char* s)
    {
        while (isspace(*s))
            ++s;
        return s;
    }

    static void split(char* cmd)
    {
        cmd = skipwhite(cmd);
        char* next = strchr(cmd, ' ');
        int i = 0;

        while (next != NULL) {
            next[0] = '\0';
            args[i] = cmd;
            ++i;
            cmd = skipwhite(next + 1);
            next = strchr(cmd, ' ');
        }

        if (cmd[0] != '\0') {
            args[i] = cmd;
            next = strchr(cmd, '\n');
            next[0] = '\0';
            ++i;
        }

        args[i] = NULL;
    }
...