Пример #1
0
 void close_unused_fds()
 {
      for(file_descriptor_type fd = min_user_file_descriptor() ; fd < max_file_descriptor() ; ++fd ) { close_unused_fd(fd); }
 }
Пример #2
0
int exec_cmd_node(cmd_node_t* cmd_node, client_node_t* client) {

    int pipe_count = cmd_node->pipe_count;
    int pid = -1;
    int input_pipe_fd = -1;
    int output_pipe_fd = -1;

    if(strcmp(cmd_node->cmd, "printenv") == 0) {
        char* env_name = cmd_node->args[1];
        if(env_name != NULL) {
            char* env_val = getenv(env_name);
            printf("%s=%s\n", env_name, env_val);
            fflush(stdout);
        }
        decrease_all_pipe_node(client->pipe_list);
        return 0;
    } else if(strcmp(cmd_node->cmd, "setenv") == 0) {
        char* env_name = cmd_node->args[1];
        char* env_val = cmd_node->args[2];
        set_env_to_client_node(client, env_name, env_val);
        setenv(env_name, env_val, 1);
        decrease_all_pipe_node(client->pipe_list);
        return 0;
    } else if(strcmp(cmd_node->cmd, "exit") == 0) {
        char exit_msg[64];
        bzero(exit_msg, 64);
        sprintf(exit_msg, "*** User '%s' left. ***\n", client->name);
        broad_cast(client, exit_msg);
        // clean message queues
        mq_clean(client->id);
        // remove global pipes
        remove_global_pipe(client->id, client->id, 0);
        // remove client from client list
        remove_client_node(client);
        // return logout status
        return -4;
    } else if(strcmp(cmd_node->cmd, "who") == 0) {
        who(client);
        decrease_all_pipe_node(client->pipe_list);
        return 0;
    } else if(strcmp(cmd_node->cmd, "tell") == 0) {
        int r = tell(client, cmd_node->args[1], cmd_node->args[2]);
        if(r == -1) {
            printf("*** Error: user #%s does not exist yet. ***\n", cmd_node->args[1]);
            fflush(stdout);
        } else {
            decrease_all_pipe_node(client->pipe_list);
        }
        return 0;
    } else if(strcmp(cmd_node->cmd, "yell") == 0) {
        char message[11000];
        sprintf(message, "*** %s yelled ***: %s\n", client->name, cmd_node->args[1]);
        bzero(message, 11000);
        broad_cast(client, message);
        decrease_all_pipe_node(client->pipe_list);
        return 0;
    } else if(strcmp(cmd_node->cmd, "name") == 0) {
        char* name = cmd_node->args[1];
        if(check_name_exist(name) == 1) {
            printf("*** User '%s' already exists. ***\n", name);
            fflush(stdout);
        } else {
            set_client_name(client->id, name);
            strcpy(client->name, name);
            char msg[40];
            bzero(msg, 40);
            sprintf(msg, "*** User from %s/%d is named '%s'. ***\n", client->ip, client->port, client->name);
            broad_cast(client, msg);
            fflush(stdout);
        }
        decrease_all_pipe_node(client->pipe_list);
        return 0;
    }

    decrease_all_pipe_node(client->pipe_list);

    // get this process input source
    pipe_node_t* in_pipe_node = find_pipe_node_by_count(client->pipe_list, 0);
    if(in_pipe_node != NULL) {
        input_pipe_fd = in_pipe_node->in_fd;
        if(fcntl(in_pipe_node->out_fd, F_GETFD) != -1) {
            close(in_pipe_node->out_fd);
        }
        in_pipe_node->count--;
    }
    if(cmd_node->pipe_from_user == 1) {
        char data[2048];
        bzero(data, 2048);
        int r = pull_global_pipe_data(cmd_node->from_user_id, client->id, data);
        if(r == -1) {
            inscrease_all_pipe_node(client->pipe_list);
            return -2;
        }
        int g_pipe[2];
        pipe(g_pipe);
        write(g_pipe[1], r.msg, strlen(r.msg));
        close(g_pipe[1]);
        input_pipe_fd = g_pipe[0];
    }
    int tmp_global_pipe[2];

    // get this process output source
    pipe_node_t* out_pipe_node = find_pipe_node_by_count(client->pipe_list, pipe_count);
    if(out_pipe_node != NULL) {
        output_pipe_fd = out_pipe_node->out_fd;
    } else if(cmd_node->pipe_to_file == 1){
        output_pipe_fd = get_file_fd(cmd_node->filename);
    } else if(cmd_node->pipe_to_user == 1) {
        if(is_client_available(cmd_node->to_user_id) != 1) {
            printf("*** Error: user #%d does not exist yet. ***\n", cmd_node->to_user_id);
            fflush(stdout);
            close_unused_fd(client);
            return 0;
        } else if(is_global_pipe_exist(client->id, cmd_node->to_user_id) == 1) {
            close_unused_fd(client);
            return -3;
        }
        // global pipe
        // create global pipe node
        pipe(tmp_global_pipe);
        output_pipe_fd = tmp_global_pipe[1];

        // broad cast message
        // *** (name) (#<client id>) just piped '(command line)' to (receiver's name) (#<receiver's client_id>) ***
        char* msg_temp = "*** %s (#%d) just piped '%s' to %s (#%d) ***\n";
        char msg[128];
        bzero(msg, 128);
        char to_client_name[30];
        get_client_name(cmd_node->to_user_id, to_client_name);
        sprintf(msg, msg_temp, client->name, client->id, last_line, to_client_name, cmd_node->to_user_id);
        broad_cast(client, msg);
        fflush(stdout);
    } else if(cmd_node->pipe_count != 0) {
        int new_pipe_fd[2];
        pipe(new_pipe_fd);
        out_pipe_node = malloc(sizeof(pipe_node_t));
        out_pipe_node->count = cmd_node->pipe_count;
        out_pipe_node->in_fd = new_pipe_fd[0];
        out_pipe_node->out_fd = new_pipe_fd[1];
        out_pipe_node->next_node = NULL;
        insert_pipe_node(&(client->pipe_list), out_pipe_node);

        output_pipe_fd = new_pipe_fd[1];
    }


    pid = fork();
    if(pid == 0) {
        if(input_pipe_fd != -1) {
            // not use stdin
            close(0);
            dup(input_pipe_fd);
            close(input_pipe_fd);
        }

        // out
        if(out_pipe_node != NULL) {
            close(1);
            dup(out_pipe_node->out_fd);
            close(out_pipe_node->out_fd);
        } else if(cmd_node->pipe_to_file == 1) {
            close(1);
            dup(output_pipe_fd);
            close(output_pipe_fd);
        } else if(cmd_node->pipe_to_user == 1) {
            close(1);
            close(2);
            dup(output_pipe_fd);
            dup(output_pipe_fd);
            close(output_pipe_fd);
        } else {
            dup2(client->client_sc_fd, 1);
        }
        execvp(cmd_node->cmd, cmd_node->args);
        exit(-1);

    } else if(pipe_count != 0) {
        int status;
        wait(&status);
        // waitpid(pid, &status, 0);
        if(WEXITSTATUS(status) != 0){
            inscrease_all_pipe_node(client->pipe_list);
            return -1;
        } else {
            if(input_pipe_fd != -1) {
                close(input_pipe_fd);
            }
        }
    } else {
        int status;
        wait(&status);
        // waitpid(pid, &status, 0);
        if(WEXITSTATUS(status) != 0){
            inscrease_all_pipe_node(client->pipe_list);
            return -1;
        } else {
            if(in_pipe_node != NULL) {
                close(in_pipe_node->out_fd);
                in_pipe_node->count--;
            }
            if(cmd_node->pipe_to_user == 1) {
                if(fcntl(output_pipe_fd, F_GETFD) != -1) {
                    close(output_pipe_fd);
                }
                char buffer[2048];
                bzero(buffer, 2048);
                read(tmp_global_pipe[0], buffer, 2048);
                //printf("[DBG] Buffer:\n");
                //printf("%s\n", buffer);
                add_global_pipe(client->id, cmd_node->to_user_id, buffer);
                close(tmp_global_pipe[0]);
            }
            close_unused_fd(client);
        }
    }
    if(cmd_node->pipe_from_user == 1) {
        char* msg_tmp = "*** %s (#%d) just received from %s (#%d) by '%s' ***\n";
        char msg[100];
        bzero(msg, 100);
        char from_client_name[30];
        get_client_name(cmd_node->from_user_id, from_client_name);
        sprintf(msg, msg_tmp, client->name, client->id, from_client_name, cmd_node->from_user_id, last_line);
        broad_cast(client, msg);
        remove_global_pipe(cmd_node->from_user_id, client->id, 1);
    }
    return 0;
}