/* * Get the current cursor Y co-ordinate by sending the ECMA-48 CPR code to * the terminal connected to the given file descriptor. */ static int pv_crs_get_ypos(int terminalfd) { struct termios tty; struct termios old_tty; char cpr[32]; int ypos; int r; #ifdef CURSOR_ANSWERBACK_BYTE_BY_BYTE int got; #endif /* CURSOR_ANSWERBACK_BYTE_BY_BYTE */ tcgetattr(terminalfd, &tty); tcgetattr(terminalfd, &old_tty); tty.c_lflag &= ~(ICANON | ECHO); tcsetattr(terminalfd, TCSANOW | TCSAFLUSH, &tty); write(terminalfd, "\033[6n", 4); memset(cpr, 0, sizeof(cpr)); #ifdef CURSOR_ANSWERBACK_BYTE_BY_BYTE /* Read answerback byte by byte - fails on AIX */ for (got = 0, r = 0; got < sizeof(cpr) - 2; got += r) { r = read(terminalfd, cpr + got, 1); if (r <= 0) { debug("got=%d, r=%d: %s", got, r, strerror(errno)); break; } if (cpr[got] == 'R') break; } debug ("read answerback message from fd %d, length %d - buf = %02X %02X %02X %02X %02X %02X", terminalfd, got, cpr[0], cpr[1], cpr[2], cpr[3], cpr[4], cpr[5]); #else /* !CURSOR_ANSWERBACK_BYTE_BY_BYTE */ /* Read answerback in one big lump - may fail on Solaris */ r = read(terminalfd, cpr, sizeof(cpr)); if (r <= 0) { debug("r=%d: %s", r, strerror(errno)); } else { debug ("read answerback message from fd %d, length %d - buf = %02X %02X %02X %02X %02X %02X", terminalfd, r, cpr[0], cpr[1], cpr[2], cpr[3], cpr[4], cpr[5]); } #endif /* CURSOR_ANSWERBACK_BYTE_BY_BYTE */ ypos = pv_getnum_i(cpr + 2); tcsetattr(terminalfd, TCSANOW | TCSAFLUSH, &old_tty); debug("%s: %d", "ypos", ypos); return ypos; }
/* * Parse the given command-line arguments into an opts_t object, handling * "help", "license" and "version" options internally. * * Returns an opts_t, or 0 on error. * * Note that the contents of *argv[] (i.e. the command line parameters) * aren't copied anywhere, just the pointers are copied, so make sure the * command line data isn't overwritten or argv[1] free()d or whatever. */ opts_t opts_parse(int argc, char **argv) { #ifdef HAVE_GETOPT_LONG struct option long_options[] = { {"help", 0, 0, 'h'}, {"version", 0, 0, 'V'}, {"progress", 0, 0, 'p'}, {"timer", 0, 0, 't'}, {"eta", 0, 0, 'e'}, {"rate", 0, 0, 'r'}, {"average-rate", 0, 0, 'a'}, {"bytes", 0, 0, 'b'}, {"force", 0, 0, 'f'}, {"numeric", 0, 0, 'n'}, {"quiet", 0, 0, 'q'}, {"cursor", 0, 0, 'c'}, {"wait", 0, 0, 'W'}, {"size", 1, 0, 's'}, {"line-mode", 0, 0, 'l'}, {"null", 0, 0, '0'}, {"interval", 1, 0, 'i'}, {"width", 1, 0, 'w'}, {"height", 1, 0, 'H'}, {"name", 1, 0, 'N'}, {"format", 1, 0, 'F'}, {"rate-limit", 1, 0, 'L'}, {"buffer-size", 1, 0, 'B'}, {"skip-errors", 0, 0, 'E'}, {"stop-at-size", 0, 0, 'S'}, {"remote", 1, 0, 'R'}, {"pidfile", 1, 0, 'P'}, {0, 0, 0, 0} }; int option_index = 0; #endif char *short_options = "hVpterabfnqcWs:l0i:w:H:N:F:L:B:ESR:P:"; int c, numopts; opts_t opts; opts = calloc(1, sizeof(*opts)); if (!opts) { fprintf(stderr, /* RATS: ignore */ _("%s: option structure allocation failed (%s)"), argv[0], strerror(errno)); fprintf(stderr, "\n"); return 0; } opts->program_name = argv[0]; opts->argc = 0; opts->argv = calloc(argc + 1, sizeof(char *)); if (!opts->argv) { fprintf(stderr, /* RATS: ignore */ _ ("%s: option structure argv allocation failed (%s)"), argv[0], strerror(errno)); fprintf(stderr, "\n"); opts_free(opts); return 0; } numopts = 0; opts->interval = 1; do { #ifdef HAVE_GETOPT_LONG c = getopt_long(argc, argv, /* RATS: ignore */ short_options, long_options, &option_index); #else c = getopt(argc, argv, short_options); /* RATS: ignore */ #endif if (c < 0) continue; /* * Check that any numeric arguments are of the right type. */ switch (c) { case 's': case 'w': case 'H': case 'L': case 'B': case 'R': if (pv_getnum_check(optarg, PV_NUMTYPE_INTEGER) != 0) { fprintf(stderr, "%s: -%c: %s\n", argv[0], c, _("integer argument expected")); opts_free(opts); return 0; } break; case 'i': if (pv_getnum_check(optarg, PV_NUMTYPE_DOUBLE) != 0) { fprintf(stderr, "%s: -%c: %s\n", argv[0], c, _("numeric argument expected")); opts_free(opts); return 0; } break; default: break; } /* * Parse each command line option. */ switch (c) { case 'h': display_help(); opts->do_nothing = 1; return opts; break; case 'V': display_version(); opts->do_nothing = 1; return opts; break; case 'p': opts->progress = 1; numopts++; break; case 't': opts->timer = 1; numopts++; break; case 'e': opts->eta = 1; numopts++; break; case 'r': opts->rate = 1; numopts++; break; case 'a': opts->average_rate = 1; numopts++; break; case 'b': opts->bytes = 1; numopts++; break; case 'f': opts->force = 1; break; case 'n': opts->numeric = 1; numopts++; break; case 'q': opts->no_op = 1; numopts++; break; case 'c': opts->cursor = 1; break; case 'W': opts->wait = 1; break; case 's': opts->size = pv_getnum_ll(optarg); break; case 'l': opts->linemode = 1; break; case '0': opts->null = 1; opts->linemode = 1; break; case 'i': opts->interval = pv_getnum_d(optarg); break; case 'w': opts->width = pv_getnum_i(optarg); break; case 'H': opts->height = pv_getnum_i(optarg); break; case 'N': opts->name = optarg; break; case 'L': opts->rate_limit = pv_getnum_ll(optarg); break; case 'B': opts->buffer_size = pv_getnum_ll(optarg); break; case 'E': opts->skip_errors++; break; case 'S': opts->stop_at_size = 1; break; case 'R': opts->remote = pv_getnum_i(optarg); break; case 'P': opts->pidfile = optarg; break; case 'F': opts->format = optarg; break; default: #ifdef HAVE_GETOPT_LONG fprintf(stderr, /* RATS: ignore (OK) */ _("Try `%s --help' for more information."), argv[0]); #else fprintf(stderr, /* RATS: ignore (OK) */ _("Try `%s -h' for more information."), argv[0]); #endif fprintf(stderr, "\n"); opts_free(opts); return 0; break; } } while (c != -1); /* * Default options: -pterb */ if (0 == numopts) { opts->progress = 1; opts->timer = 1; opts->eta = 1; opts->rate = 1; opts->bytes = 1; } /* * Store remaining command-line arguments. */ while (optind < argc) { opts->argv[opts->argc++] = argv[optind++]; } return opts; }