#include #include #include #include "job.h" // 문자열을 공백 기준으로 쪼개서 argv에 넣기 static void parse_args(char *cmd_str, command_t *cmd) { char *token = strtok(cmd_str, " \t\n"); while (token != NULL && cmd->argc < MAX_ARGS - 1) { // 리다이렉션 처리 (간이 버전) if (strcmp(token, "<") == 0) { token = strtok(NULL, " \t\n"); if (token) cmd->input_path = strdup(token); } else if (strcmp(token, ">") == 0) { token = strtok(NULL, " \t\n"); if (token) cmd->output_path = strdup(token); cmd->append_mode = 0; } else if (strcmp(token, ">>") == 0) { token = strtok(NULL, " \t\n"); if (token) cmd->output_path = strdup(token); cmd->append_mode = 1; } else { // 일반 인자 cmd->argv[cmd->argc++] = strdup(token); } token = strtok(NULL, " \t\n"); } cmd->argv[cmd->argc] = NULL; } // 메인 파서 함수 job_t *parse_line(char *line) { if (line == NULL || strlen(line) == 0) return NULL; // 1. Job 껍데기 생성 job_t *job = create_job(line); // 2. 백그라운드(&) 확인 // 문자열 끝에서부터 역탐색하거나, 토큰화 과정에서 체크해야 함. // 편의상 strrchr 사용 (단, 따옴표 안에 있는 &는 무시 못함. 일단 간단히 구현) char *bg_ptr = strrchr(line, '&'); if (bg_ptr != NULL) { job->is_bg = 1; *bg_ptr = ' '; // &를 공백으로 치환해서 명령어 파싱 방해 안 되게 함 } // 3. 파이프(|) 단위로 자르기 // strtok는 원본을 훼손하므로 복사본 사용 char *line_copy = strdup(line); char *cmd_str = strtok(line_copy, "|"); while (cmd_str != NULL) { command_t *cmd = (command_t *)malloc(sizeof(command_t)); memset(cmd, 0, sizeof(command_t)); // 내부 인자 및 리다이렉션 파싱 parse_args(cmd_str, cmd); if (cmd->argc > 0) { append_command(job, cmd); } else { free(cmd); // 빈 명령어는 버림 } cmd_str = strtok(NULL, "|"); } free(line_copy); if (job->head == NULL) { // 명령어가 하나도 없으면 free_job(job); return NULL; } return job; }