int main(int argc, char *const argv[]) { int opt = 0, long_index = 0, status = 0; FILE *lf = stderr; /**< Default logfile. */ char *lfpath = NULL; cli_code cli_stat = CLI_PRE_INIT; /* Parse command-line arguments. */ while ((opt = getopt_long(argc, argv, g_short_opts, g_long_opts, &long_index)) != -1) { switch (opt) { case 'l': if (!optarg) { fputs("The logfile option requires a valid argument.\n", stderr); status = 1; goto exit; } if (!(lf = freopen(optarg, "a+", stderr))) { fprintf(stderr, "Could not open logfile '%s'!\n", optarg); perror("logfile"); status = 2; goto exit; } if (!(lfpath = strndup(optarg, strlen(optarg) + 1))) { perror("logfile path strndup"); status = 3; goto exit; } fprintf(stderr, "\t*** Logfile: '%s' ***\n", lfpath); break; case 'h': usage(); goto exit; default: break; } } if (!lfpath) { char *tmpname = strdup("/tmp/chemtk_dbg_XXXXXX"); assert(tmpname); int tmpfile = mkstemp(tmpname); lfpath = tmpname; if (tmpfile == -1) { perror("mkstemp"); goto exit; } if (!(lf = freopen(tmpname, "a+", stderr))) { fprintf(stderr, "Could not open logfile '%s'!\n", tmpname); perror("logfile"); status = 2; goto exit; } } cli_stat = run_cli(stderr); printf("CLI exited: %s\n", cli_statuses[cli_stat]); if (cli_stat != CLI_OK) status = 100 + cli_stat; exit: if (lf != stderr && lf != NULL) fclose(lf); if (lfpath) { if (unlink(lfpath) == -1) { fprintf(stderr, "Could not unlink '%s'.\n", lfpath); perror("unlink"); } } free(lfpath); delete_sc_stack(g_stack, free); free_command_info(); return status; }
// parse command to run // parse tokens from head (include) to tail (*exclude*) PARSE_STATUS parse_command(TOKEN_LIST_NODE *head, TOKEN_LIST_NODE *tail) { COMMAND_INFO info; char *temp, *pwd; int i; init_command_info(&info); while (head != tail) { switch (head->tok->type) { case TOKEN_TYPE_IN: // move to next token head = head->next; // must be a string after the < operator if (head->tok->type != TOKEN_TYPE_STRING) { free_command_info(info); return PARSE_STATUS_FILENAME_EXPECTED; } // check if file not exist pwd = calloc(sizeof(char *), STRING_MAX_LENGTH); getcwd(pwd, STRING_MAX_LENGTH); temp = connect_dir(pwd, head->tok->t_string.str); free(pwd); if (access(temp, 0) == -1) { free_command_info(info); return PARSE_STATUS_FILE_NOT_EXIST; } free(temp); info.input_file = head->tok->t_string.str; break; case TOKEN_TYPE_OUT: // move to next token head = head->next; // must be a string after the < operator if (head->tok->type != TOKEN_TYPE_STRING) { free_command_info(info); return PARSE_STATUS_FILENAME_EXPECTED; } // if file not exist, create it, or clear it close(open(head->tok->t_string.str, O_WRONLY | O_CREAT, 0644)); info.output_file = head->tok->t_string.str; info.append_mode = 0; break; case TOKEN_TYPE_APPEND: // move to next token head = head->next; // must be a string after the < operator if (head->tok->type != TOKEN_TYPE_STRING) { free_command_info(info); return PARSE_STATUS_FILENAME_EXPECTED; } // if file not exist, create it, or do nothing close(open(head->tok->t_string.str, O_WRONLY | O_CREAT | O_APPEND, 0644)); info.output_file = head->tok->t_string.str; info.append_mode = 1; break; case TOKEN_TYPE_STRING: // the first string is always command if (info.command == NULL) { info.command = head->tok->t_string.str; } // add this string to parameters ++info.parameters_len; info.parameters = realloc(info.parameters, sizeof(char *) * info.parameters_len); info.parameters[info.parameters_len - 1] = head->tok->t_string.str; break; case TOKEN_TYPE_BG: info.background_mode = 1; break; case TOKEN_TYPE_PIPE: info.output_to_pipe = 1; break; case TOKEN_TYPE_NEXT: info.wait_processes = 1; // other tokens default: // do nothing break; } head = head->next; } // If command equals to NULL... Hey, you are kidding. // No commands here, what should I run instead? if (info.command == NULL) { free_command_info(info); return PARSE_STATUS_COMMAND_EXPECTED; } else { #ifdef DEBUG fprintf(stderr, "[parser.c] will run command %s!\n", info.command); #endif run_command(&info); if (info.wait_processes) { for (i = 0; i != pid_list_len; ++i) { waitpid(pid_list[i]); } free(pid_list); pid_list = NULL; pid_list_len = 0; } free_command_info(info); return PARSE_STATUS_NORMAL; } }