void parse_monitor_options(int argc, char ** argv, dtnperf_global_options_t * perf_g_opt) { char c, done = 0; boolean_t output_set = FALSE; dtnperf_options_t * perf_opt = perf_g_opt->perf_opt; // kill daemon variables int pid; char cmd[256]; while (!done) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, {"debug", optional_argument, 0, 33}, {"ldir", required_argument, 0, 40}, {"ip-addr", required_argument, 0, 37}, {"ip-port", required_argument, 0, 38}, {"daemon", no_argument, 0, 'a'}, {"output", required_argument, 0, 'o'}, {"stop", no_argument, 0, 's'}, {0,0,0,0} // The last element of the array has to be filled with zeros. }; int option_index = 0; c = getopt_long(argc, argv, "hvao:s", long_options, &option_index); switch (c) { case 'h': print_monitor_usage(argv[0]); exit(0); return ; case 'v': perf_opt->verbose = TRUE; break; case 33: // debug perf_opt->debug = TRUE; if (optarg != NULL){ int debug_level = atoi(optarg); if (debug_level >= 1 && debug_level <= 2) perf_opt->debug_level = atoi(optarg) -1; else { fprintf(stderr, "wrong --debug argument\n"); exit(1); return; } } else perf_opt->debug_level = 2; break; case 37: perf_opt->ip_addr = strdup(optarg); perf_opt->use_ip = TRUE; break; case 38: perf_opt->ip_port = atoi(optarg); perf_opt->use_ip = TRUE; break; case 40: perf_opt->logs_dir = strdup(optarg); break; case 'a': perf_opt->daemon = TRUE; break; case 'o': perf_opt->monitor_output_file = strdup(optarg); output_set = TRUE; break; case 's': memset(cmd, 0, sizeof(cmd)); sprintf(cmd, "%s %s", argv[0], MONITOR_STRING); pid = find_proc(cmd); if (pid) { printf("Closing dtnperf monitor pid: %d\n", pid); kill(pid, SIGINT); } else { fprintf(stderr, "ERROR: cannot find a running instance of dtnperf monitor\n"); } exit(0); break; case '?': break; case (char)(-1): done = 1; break; default: // getopt already prints an error message for unknown option characters print_monitor_usage(argv[0]); exit(1); } } if (output_set && !perf_opt->daemon) { fprintf(stderr, "\nSYNTAX ERROR: -o option can be used only with -a option\n"); \ print_monitor_usage(argv[0]); \ exit(1); } }
int monitor(int argc, char *argv[]) { ty_board *board = NULL; int outfd = -1; int r; int c; while ((c = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (c) { HANDLE_COMMON_OPTIONS(c, print_monitor_usage); case 's': terminal_flags |= TY_TERMINAL_SILENT; break; case 'r': terminal_flags |= TY_TERMINAL_RAW; break; case 'D': if (strcmp(optarg, "input") == 0) { directions = DIRECTION_INPUT; } else if (strcmp(optarg, "output") == 0) { directions = DIRECTION_OUTPUT; } else if (strcmp(optarg, "both") == 0) { directions = DIRECTION_INPUT | DIRECTION_OUTPUT; } else { ty_log(TY_LOG_ERROR, "--direction must be one off input, output or both"); print_monitor_usage(stderr); return EXIT_FAILURE; } break; case 'b': errno = 0; device_rate = (uint32_t)strtoul(optarg, NULL, 10); if (errno) { ty_log(TY_LOG_ERROR, "--baud requires a number"); print_monitor_usage(stderr); return EXIT_FAILURE; } break; case 'd': device_flags &= ~HS_SERIAL_MASK_CSIZE; if (strcmp(optarg, "5") == 0) { device_flags |= HS_SERIAL_CSIZE_5BITS; } else if (strcmp(optarg, "6") == 0) { device_flags |= HS_SERIAL_CSIZE_6BITS; } else if (strcmp(optarg, "7") == 0) { device_flags |= HS_SERIAL_CSIZE_7BITS; } else if (strcmp(optarg, "8") != 0) { ty_log(TY_LOG_ERROR, "--databits must be one off 5, 6, 7 or 8"); print_monitor_usage(stderr); return EXIT_FAILURE; } case 'f': device_flags &= ~HS_SERIAL_MASK_FLOW; if (strcmp(optarg, "x") == 0 || strcmp(optarg, "xonxoff") == 0) { device_flags |= HS_SERIAL_FLOW_XONXOFF; } else if (strcmp(optarg, "h") == 0 || strcmp(optarg, "rtscts") == 0) { device_flags |= HS_SERIAL_FLOW_RTSCTS; } else if (strcmp(optarg, "n") != 0 && strcmp(optarg, "none") == 0) { ty_log(TY_LOG_ERROR, "--flow must be one off x (xonxoff), h (rtscts) or n (none)"); print_monitor_usage(stderr); return EXIT_FAILURE; } break; case MONITOR_OPTION_NORESET: device_flags |= HS_SERIAL_CLOSE_NOHUP; break; case 'p': device_flags &= ~HS_SERIAL_MASK_PARITY; if (strcmp(optarg, "o") == 0 || strcmp(optarg, "odd") == 0) { device_flags |= HS_SERIAL_PARITY_ODD; } else if (strcmp(optarg, "e") == 0 || strcmp(optarg, "even") == 0) { device_flags |= HS_SERIAL_PARITY_EVEN; } else if (strcmp(optarg, "n") != 0 && strcmp(optarg, "none") != 0) { ty_log(TY_LOG_ERROR, "--parity must be one off o (odd), e (even) or n (none)"); print_monitor_usage(stderr); return EXIT_FAILURE; } break; case 'R': reconnect = true; break; case MONITOR_OPTION_TIMEOUT_EOF: errno = 0; timeout_eof = (int)strtol(optarg, NULL, 10); if (errno) { ty_log(TY_LOG_ERROR, "--timeout requires a number"); print_monitor_usage(stderr); return EXIT_FAILURE; } if (timeout_eof < 0) timeout_eof = -1; break; } } if (argc > optind) { ty_log(TY_LOG_ERROR, "No positional argument is allowed"); print_monitor_usage(stderr); return EXIT_FAILURE; } if (ty_standard_get_modes(TY_STANDARD_INPUT) & TY_DESCRIPTOR_MODE_TERMINAL) { #ifdef _WIN32 if (terminal_flags & TY_TERMINAL_RAW && !(terminal_flags & TY_TERMINAL_SILENT)) { terminal_flags |= TY_TERMINAL_SILENT; if (ty_standard_get_modes(TY_STANDARD_OUTPUT) & TY_DESCRIPTOR_MODE_TERMINAL) fake_echo = true; } /* Unlike POSIX platforms, Windows does not implement the console line editing behavior * at the tty layer. Instead, ReadFile() takes care of it and blocks until return is hit. * The problem is that the Wait functions will return the stdin descriptor as soon as * something is typed but then, ReadFile() will block until return is pressed. * Overlapped I/O cannot be used because it is not supported on console descriptors. * * So the best way I found is to have a background thread handle the blocking ReadFile() * and pass the lines in a buffer. When a new line is entered, the input_available * event is set to signal the poll in loop(). I also tried to use an anonymous pipe to * make it simpler, but the Wait functions do not support them. */ if (directions & DIRECTION_OUTPUT && !(terminal_flags & TY_TERMINAL_RAW)) { r = start_stdin_thread(); if (r < 0) goto cleanup; } #endif r = ty_terminal_setup(terminal_flags); if (r < 0) goto cleanup; } r = redirect_stdout(&outfd); if (r < 0) goto cleanup; r = get_board(&board); if (r < 0) goto cleanup; r = loop(board, outfd); cleanup: #ifdef _WIN32 stop_stdin_thread(); #endif ty_board_unref(board); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }