/* Writes up to size bytes from buffer to the file open with descriptor fd, and returns the actual number written (may be less than size if EOF is reached), or -1 if no file is open as fd or the write fails for another reason. Writing to 1 will print to standard output */ static int sys_write (int fd, const void *buffer, unsigned size) { int written; struct file_fd *ffd; check_ptr (buffer); switch (fd) { case 0: return 0; case 1: putbuf ((char *) buffer, size); return size; case 2: return 0; default: ffd = get_file_fd (fd); if (ffd == NULL) return 0; lock_acquire (&fs_lock); written = file_write (ffd->file, buffer, size); lock_release (&fs_lock); return written; } }
/* Reads up to size bytes from the file open with descriptor fd into buffer, and returns the actual number of bytes read (may be less than size if EOF is reached), or -1 if no file is open as fd, or the read fails for any other reason. Calling read with fd = 0 will read input from standard input, blocking until size bytes have been read */ static int sys_read (int fd, void *buffer, unsigned size) { check_ptr (buffer); unsigned read; struct file_fd *ffd; char *char_buffer = buffer; switch (fd) { case 0: for (read = 0; read < size; read++) { char_buffer[read] = input_getc (); } return read; case 1: return -1; case 2: return -1; default: ffd = get_file_fd (fd); if (ffd == NULL) return -1; lock_acquire (&fs_lock); read = file_read (ffd->file, buffer, size); lock_release (&fs_lock); return read; } }
void prepare_files(run_param* run, int * input_fd, int * output_fd, int * code_fd) { get_file_fd(run->problem_id, input_fd, INPUT_DIR, "test.in", O_RDONLY); *output_fd = open("out.out", O_WRONLY|O_CREAT, S_IRWXU| S_IRWXG| S_IRWXO); ftruncate(*output_fd, 0); syslog(LOG_DEBUG, "prob num : %d.",run->problem_id); syslog(LOG_DEBUG, "code file : %s.",code_file_name[run->lang]); *code_fd = open(code_file_name[run->lang], O_WRONLY|O_CREAT); ftruncate(*code_fd, 0); };
/* Moves the current pointer of the file open as fd to position bytes ahead of the start of the file. Does nothing if no file is open as fd */ static void sys_seek (int fd, unsigned position) { struct file_fd *ffd; ffd = get_file_fd (fd); if (ffd == NULL) return; lock_acquire (&fs_lock); file_seek (ffd->file, position); lock_release (&fs_lock); }
/* Returns the size in bytes of the file with descriptor fd. If no file is open with descriptor fd or if the filesize could not be read for any other reason, returns -1 */ static int sys_filesize (int fd) { struct file_fd *ffd = get_file_fd (fd); int length; if (ffd == NULL) return -1; lock_acquire (&fs_lock); length = file_length (ffd->file); lock_release (&fs_lock); return length; }
/* Closes the file open with file descriptor fd, or does nothing if no such file exists */ static void sys_close (int fd) { struct file_fd *ffd = get_file_fd (fd); if (ffd == NULL) return; else { list_remove (&ffd->elem); lock_acquire (&fs_lock); file_close (ffd->file); lock_release (&fs_lock); free (ffd); } }
/* Returns the number of bytes ahead of the start of the file the current pointer is for the file open as fd, or -1 if no file is open as fd or the tell fails for any other reason */ static unsigned sys_tell (int fd) { unsigned next_byte; struct file_fd *ffd; ffd = get_file_fd (fd); if (ffd == NULL) // Proper error value? return -1; lock_acquire (&fs_lock); next_byte = file_tell (ffd->file); lock_release (&fs_lock); return next_byte; }
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; }