diff options
Diffstat (limited to 'coreutils')
| -rw-r--r-- | coreutils/stty.c | 412 |
1 files changed, 241 insertions, 171 deletions
diff --git a/coreutils/stty.c b/coreutils/stty.c index d709bfc1e..a63c1d1fa 100644 --- a/coreutils/stty.c +++ b/coreutils/stty.c | |||
| @@ -173,7 +173,7 @@ struct mode_info { | |||
| 173 | 173 | ||
| 174 | #define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B } | 174 | #define MI_ENTRY(N,T,F,B,M) { N, T, F, M, B } |
| 175 | 175 | ||
| 176 | static const struct mode_info mode_info[] = { | 176 | static const struct mode_info mode_info[] = { |
| 177 | MI_ENTRY("parenb", control, REV, PARENB, 0 ), | 177 | MI_ENTRY("parenb", control, REV, PARENB, 0 ), |
| 178 | MI_ENTRY("parodd", control, REV, PARODD, 0 ), | 178 | MI_ENTRY("parodd", control, REV, PARODD, 0 ), |
| 179 | MI_ENTRY("cs5", control, 0, CS5, CSIZE), | 179 | MI_ENTRY("cs5", control, 0, CS5, CSIZE), |
| @@ -333,7 +333,7 @@ struct control_info { | |||
| 333 | 333 | ||
| 334 | /* Control characters. */ | 334 | /* Control characters. */ |
| 335 | 335 | ||
| 336 | static const struct control_info control_info[] = { | 336 | static const struct control_info control_info[] = { |
| 337 | {"intr", CINTR, VINTR}, | 337 | {"intr", CINTR, VINTR}, |
| 338 | {"quit", CQUIT, VQUIT}, | 338 | {"quit", CQUIT, VQUIT}, |
| 339 | {"erase", CERASE, VERASE}, | 339 | {"erase", CERASE, VERASE}, |
| @@ -380,9 +380,9 @@ enum { | |||
| 380 | #define EMT(t) ((enum mode_type)(t)) | 380 | #define EMT(t) ((enum mode_type)(t)) |
| 381 | 381 | ||
| 382 | static const char * visible(unsigned int ch); | 382 | static const char * visible(unsigned int ch); |
| 383 | static int recover_mode(char *arg, struct termios *mode); | 383 | static int recover_mode(const char *arg, struct termios *mode); |
| 384 | static int screen_columns(void); | 384 | static int screen_columns(void); |
| 385 | static int set_mode(const struct mode_info *info, | 385 | static void set_mode(const struct mode_info *info, |
| 386 | int reversed, struct termios *mode); | 386 | int reversed, struct termios *mode); |
| 387 | static speed_t string_to_baud(const char *arg); | 387 | static speed_t string_to_baud(const char *arg); |
| 388 | static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode); | 388 | static tcflag_t* mode_type_flag(enum mode_type type, struct termios *mode); |
| @@ -398,7 +398,7 @@ static void set_speed(enum speed_setting type, | |||
| 398 | const char *arg, struct termios *mode); | 398 | const char *arg, struct termios *mode); |
| 399 | static void set_window_size(int rows, int cols); | 399 | static void set_window_size(int rows, int cols); |
| 400 | 400 | ||
| 401 | static const char *device_name; | 401 | static const char *device_name = bb_msg_standard_input; |
| 402 | 402 | ||
| 403 | static ATTRIBUTE_NORETURN void perror_on_device(const char *fmt) | 403 | static ATTRIBUTE_NORETURN void perror_on_device(const char *fmt) |
| 404 | { | 404 | { |
| @@ -445,80 +445,192 @@ static const struct suffix_mult stty_suffixes[] = { | |||
| 445 | {NULL, 0 } | 445 | {NULL, 0 } |
| 446 | }; | 446 | }; |
| 447 | 447 | ||
| 448 | static const struct mode_info *find_mode(const char *name) | ||
| 449 | { | ||
| 450 | int i; | ||
| 451 | for (i = 0; i < NUM_mode_info; ++i) | ||
| 452 | if (STREQ(name, mode_info[i].name)) | ||
| 453 | return &mode_info[i]; | ||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | |||
| 457 | static const struct control_info *find_control(const char *name) | ||
| 458 | { | ||
| 459 | int i; | ||
| 460 | for (i = 0; i < NUM_control_info; ++i) | ||
| 461 | if (STREQ(name, control_info[i].name)) | ||
| 462 | return &control_info[i]; | ||
| 463 | return 0; | ||
| 464 | } | ||
| 465 | |||
| 466 | enum { | ||
| 467 | param_need_arg = 0x80, | ||
| 468 | param_line = 1 | 0x80, | ||
| 469 | param_rows = 2 | 0x80, | ||
| 470 | param_cols = 3 | 0x80, | ||
| 471 | param_size = 4, | ||
| 472 | param_ispeed = 5 | 0x80, | ||
| 473 | param_ospeed = 6 | 0x80, | ||
| 474 | param_speed = 7, | ||
| 475 | }; | ||
| 476 | |||
| 477 | static int find_param(const char *name) | ||
| 478 | { | ||
| 479 | #ifdef HAVE_C_LINE | ||
| 480 | if (STREQ(name, "line")) return param_line; | ||
| 481 | #endif | ||
| 482 | #ifdef TIOCGWINSZ | ||
| 483 | if (STREQ(name, "rows")) return param_rows; | ||
| 484 | if (STREQ(name, "cols")) return param_cols; | ||
| 485 | if (STREQ(name, "columns")) return param_cols; | ||
| 486 | if (STREQ(name, "size")) return param_size; | ||
| 487 | #endif | ||
| 488 | if (STREQ(name, "ispeed")) return param_ispeed; | ||
| 489 | if (STREQ(name, "ospeed")) return param_ospeed; | ||
| 490 | if (STREQ(name, "speed")) return param_speed; | ||
| 491 | return 0; | ||
| 492 | } | ||
| 493 | |||
| 494 | |||
| 448 | int stty_main(int argc, char **argv) | 495 | int stty_main(int argc, char **argv) |
| 449 | { | 496 | { |
| 450 | struct termios mode; | 497 | struct termios mode; |
| 451 | void (*output_func)(struct termios *); | 498 | void (*output_func)(struct termios *); |
| 452 | int optc; | 499 | const char *file_name = NULL; |
| 453 | int require_set_attr; | 500 | int require_set_attr; |
| 454 | int speed_was_set; | 501 | int speed_was_set; |
| 455 | int verbose_output; | 502 | int verbose_output; |
| 456 | int recoverable_output; | 503 | int recoverable_output; |
| 457 | int k; | 504 | int noargs; |
| 458 | int noargs = 1; | 505 | int k; |
| 459 | char * file_name = NULL; | ||
| 460 | 506 | ||
| 461 | output_func = display_changed; | 507 | output_func = display_changed; |
| 508 | noargs = 1; | ||
| 509 | speed_was_set = 0; | ||
| 510 | require_set_attr = 0; | ||
| 462 | verbose_output = 0; | 511 | verbose_output = 0; |
| 463 | recoverable_output = 0; | 512 | recoverable_output = 0; |
| 464 | 513 | ||
| 465 | /* Don't print error messages for unrecognized options. */ | 514 | /* First pass: only parse/verify command line params */ |
| 466 | opterr = 0; | 515 | k = 0; |
| 467 | 516 | while (argv[++k]) { | |
| 468 | while ((optc = getopt(argc, argv, "agF:")) != -1) { | 517 | const struct mode_info *mp; |
| 469 | switch (optc) { | 518 | const struct control_info *cp; |
| 470 | case 'a': | 519 | const char *arg = argv[k]; |
| 471 | verbose_output = 1; | 520 | const char *argnext = argv[k+1]; |
| 472 | output_func = display_all; | 521 | int param; |
| 473 | break; | 522 | |
| 474 | 523 | if (arg[0] == '-') { | |
| 475 | case 'g': | 524 | int i; |
| 476 | recoverable_output = 1; | 525 | mp = find_mode(arg+1); |
| 477 | output_func = display_recoverable; | 526 | if (mp) { |
| 478 | break; | 527 | if (!(mp->flags & REV)) |
| 528 | bb_error_msg_and_die("invalid argument '%s'", arg); | ||
| 529 | noargs = 0; | ||
| 530 | continue; | ||
| 531 | } | ||
| 532 | /* It is an option - parse it */ | ||
| 533 | i = 0; | ||
| 534 | while (arg[++i]) { | ||
| 535 | switch (arg[i]) { | ||
| 536 | case 'a': | ||
| 537 | verbose_output = 1; | ||
| 538 | output_func = display_all; | ||
| 539 | break; | ||
| 540 | case 'g': | ||
| 541 | recoverable_output = 1; | ||
| 542 | output_func = display_recoverable; | ||
| 543 | break; | ||
| 544 | case 'F': | ||
| 545 | if (file_name) | ||
| 546 | bb_error_msg_and_die("only one device may be specified"); | ||
| 547 | file_name = &arg[i+1]; /* "-Fdevice" ? */ | ||
| 548 | if (!file_name[0]) { /* nope, "-F device" */ | ||
| 549 | int p = k+1; /* argv[p] is argnext */ | ||
| 550 | file_name = argnext; | ||
| 551 | if (!file_name) | ||
| 552 | bb_error_msg_and_die(bb_msg_requires_arg, "-F"); | ||
| 553 | /* remove -F param from arg[vc] */ | ||
| 554 | --argc; | ||
| 555 | while (argv[p+1]) { argv[p] = argv[p+1]; ++p; } | ||
| 556 | } | ||
| 557 | goto end_option; | ||
| 558 | default: | ||
| 559 | bb_error_msg_and_die("invalid argument '%s'", arg); | ||
| 560 | } | ||
| 561 | } | ||
| 562 | end_option: | ||
| 563 | continue; | ||
| 564 | } | ||
| 479 | 565 | ||
| 480 | case 'F': | 566 | mp = find_mode(arg); |
| 481 | if (file_name) | 567 | if (mp) { |
| 482 | bb_error_msg_and_die("only one device may be specified"); | 568 | noargs = 0; |
| 483 | file_name = optarg; | 569 | continue; |
| 484 | break; | 570 | } |
| 485 | 571 | ||
| 486 | default: /* unrecognized option */ | 572 | cp = find_control(arg); |
| 573 | if (cp) { | ||
| 574 | if (!argnext) | ||
| 575 | bb_error_msg_and_die(bb_msg_requires_arg, arg); | ||
| 487 | noargs = 0; | 576 | noargs = 0; |
| 488 | break; | 577 | ++k; |
| 578 | continue; | ||
| 489 | } | 579 | } |
| 490 | 580 | ||
| 491 | if (noargs == 0) | 581 | param = find_param(arg); |
| 492 | break; | 582 | if (param & param_need_arg) { |
| 493 | } | 583 | if (!argnext) |
| 584 | bb_error_msg_and_die(bb_msg_requires_arg, arg); | ||
| 585 | ++k; | ||
| 586 | } | ||
| 494 | 587 | ||
| 495 | if (optind < argc) | 588 | switch (param) { |
| 589 | #ifdef HAVE_C_LINE | ||
| 590 | case param_line: | ||
| 591 | bb_xparse_number(argnext, stty_suffixes); | ||
| 592 | break; | ||
| 593 | #endif | ||
| 594 | #ifdef TIOCGWINSZ | ||
| 595 | case param_rows: | ||
| 596 | bb_xparse_number(argnext, stty_suffixes); | ||
| 597 | break; | ||
| 598 | case param_cols: | ||
| 599 | bb_xparse_number(argnext, stty_suffixes); | ||
| 600 | break; | ||
| 601 | case param_size: | ||
| 602 | #endif | ||
| 603 | case param_ispeed: | ||
| 604 | case param_ospeed: | ||
| 605 | case param_speed: | ||
| 606 | break; | ||
| 607 | default: | ||
| 608 | if (recover_mode(arg, &mode) == 1) break; | ||
| 609 | if (string_to_baud(arg) != (speed_t) -1) break; | ||
| 610 | bb_error_msg_and_die("invalid argument '%s'", arg); | ||
| 611 | } | ||
| 496 | noargs = 0; | 612 | noargs = 0; |
| 613 | } | ||
| 497 | 614 | ||
| 498 | /* Specifying both -a and -g gets an error. */ | 615 | /* Specifying both -a and -g is an error */ |
| 499 | if (verbose_output & recoverable_output) | 616 | if (verbose_output && recoverable_output) |
| 500 | bb_error_msg_and_die ("verbose and stty-readable output styles are mutually exclusive"); | 617 | bb_error_msg_and_die("verbose and stty-readable output styles are mutually exclusive"); |
| 501 | 618 | /* Specifying -a or -g with non-options is an error */ | |
| 502 | /* Specifying any other arguments with -a or -g gets an error. */ | 619 | if (!noargs && (verbose_output || recoverable_output)) |
| 503 | if (~noargs & (verbose_output | recoverable_output)) | 620 | bb_error_msg_and_die("modes may not be set when specifying an output style"); |
| 504 | bb_error_msg_and_die ("modes may not be set when specifying an output style"); | ||
| 505 | |||
| 506 | /* FIXME: it'd be better not to open the file until we've verified | ||
| 507 | that all arguments are valid. Otherwise, we could end up doing | ||
| 508 | only some of the requested operations and then failing, probably | ||
| 509 | leaving things in an undesirable state. */ | ||
| 510 | 621 | ||
| 622 | /* Now it is safe to start doing things */ | ||
| 511 | if (file_name) { | 623 | if (file_name) { |
| 512 | int fdflags; | 624 | int fd, fdflags; |
| 513 | |||
| 514 | device_name = file_name; | 625 | device_name = file_name; |
| 515 | fclose(stdin); | 626 | fd = xopen(device_name, O_RDONLY | O_NONBLOCK); |
| 516 | xopen(device_name, O_RDONLY | O_NONBLOCK); | 627 | if (fd != 0) { |
| 628 | dup2(fd, 0); | ||
| 629 | close(fd); | ||
| 630 | } | ||
| 517 | fdflags = fcntl(STDIN_FILENO, F_GETFL); | 631 | fdflags = fcntl(STDIN_FILENO, F_GETFL); |
| 518 | if (fdflags == -1 || fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0) | 632 | if (fdflags == -1 || fcntl(STDIN_FILENO, F_SETFL, fdflags & ~O_NONBLOCK) < 0) |
| 519 | perror_on_device("%s: couldn't reset non-blocking mode"); | 633 | perror_on_device("%s: couldn't reset non-blocking mode"); |
| 520 | } else { | ||
| 521 | device_name = bb_msg_standard_input; | ||
| 522 | } | 634 | } |
| 523 | 635 | ||
| 524 | /* Initialize to all zeroes so there is no risk memcmp will report a | 636 | /* Initialize to all zeroes so there is no risk memcmp will report a |
| @@ -527,122 +639,92 @@ int stty_main(int argc, char **argv) | |||
| 527 | if (tcgetattr(STDIN_FILENO, &mode)) | 639 | if (tcgetattr(STDIN_FILENO, &mode)) |
| 528 | perror_on_device("%s"); | 640 | perror_on_device("%s"); |
| 529 | 641 | ||
| 530 | if (verbose_output | recoverable_output | noargs) { | 642 | if (verbose_output || recoverable_output || noargs) { |
| 531 | max_col = screen_columns(); | 643 | max_col = screen_columns(); |
| 532 | current_col = 0; | 644 | current_col = 0; |
| 533 | output_func(&mode); | 645 | output_func(&mode); |
| 534 | return EXIT_SUCCESS; | 646 | return EXIT_SUCCESS; |
| 535 | } | 647 | } |
| 536 | 648 | ||
| 537 | speed_was_set = 0; | 649 | /* Second pass: perform actions */ |
| 538 | require_set_attr = 0; | ||
| 539 | k = 0; | 650 | k = 0; |
| 540 | while (++k < argc) { | 651 | while (argv[++k]) { |
| 541 | int match_found = 0; | 652 | const struct mode_info *mp; |
| 542 | int reversed = 0; | 653 | const struct control_info *cp; |
| 543 | int i; | 654 | const char *arg = argv[k]; |
| 544 | 655 | const char *argnext = argv[k+1]; | |
| 545 | if (argv[k][0] == '-') { | 656 | int param; |
| 546 | char *find_dev_opt; | 657 | |
| 547 | 658 | if (arg[0] == '-') { | |
| 548 | ++argv[k]; | 659 | mp = find_mode(arg+1); |
| 549 | 660 | if (mp) { | |
| 550 | /* Handle "-a", "-ag", "-aF/dev/foo", "-aF /dev/foo", etc. | 661 | set_mode(mp, 1 /* reversed */, &mode); |
| 551 | Find the options that have been parsed. This is really | ||
| 552 | gross, but it's needed because stty SETTINGS look like options to | ||
| 553 | getopt(), so we need to work around things in a really horrible | ||
| 554 | way. If any new options are ever added to stty, the short option | ||
| 555 | MUST NOT be a letter which is the first letter of one of the | ||
| 556 | possible stty settings. | ||
| 557 | */ | ||
| 558 | find_dev_opt = strchr(argv[k], 'F'); /* find -*F* */ | ||
| 559 | if(find_dev_opt) { | ||
| 560 | if(find_dev_opt[1]==0) /* -*F /dev/foo */ | ||
| 561 | k++; /* skip /dev/foo */ | ||
| 562 | continue; /* else -*F/dev/foo - no skip */ | ||
| 563 | } | 662 | } |
| 564 | if(argv[k][0]=='a' || argv[k][0]=='g') | 663 | /* It is an option - already parsed. Skip it */ |
| 565 | continue; | 664 | continue; |
| 566 | /* Is not options - is reverse params */ | ||
| 567 | reversed = 1; | ||
| 568 | } | 665 | } |
| 569 | for (i = 0; i < NUM_mode_info; ++i) | ||
| 570 | if (STREQ(argv[k], mode_info[i].name)) { | ||
| 571 | match_found = set_mode(&mode_info[i], reversed, &mode); | ||
| 572 | require_set_attr = 1; | ||
| 573 | break; | ||
| 574 | } | ||
| 575 | 666 | ||
| 576 | if (match_found == 0 && reversed) | 667 | mp = find_mode(arg); |
| 577 | bb_error_msg_and_die("invalid argument `%s'", --argv[k]); | 668 | if (mp) { |
| 578 | 669 | set_mode(mp, 0 /* non-reversed */, &mode); | |
| 579 | if (match_found == 0) | 670 | continue; |
| 580 | for (i = 0; i < NUM_control_info; ++i) | 671 | } |
| 581 | if (STREQ(argv[k], control_info[i].name)) { | ||
| 582 | if (k == argc - 1) | ||
| 583 | bb_error_msg_and_die(bb_msg_requires_arg, argv[k]); | ||
| 584 | match_found = 1; | ||
| 585 | ++k; | ||
| 586 | set_control_char(&control_info[i], argv[k], &mode); | ||
| 587 | require_set_attr = 1; | ||
| 588 | break; | ||
| 589 | } | ||
| 590 | 672 | ||
| 591 | if (match_found == 0) { | 673 | cp = find_control(arg); |
| 592 | if (STREQ(argv[k], "ispeed")) { | 674 | if (cp) { |
| 593 | if (k == argc - 1) | 675 | ++k; |
| 594 | bb_error_msg_and_die(bb_msg_requires_arg, argv[k]); | 676 | set_control_char(cp, argnext, &mode); |
| 595 | ++k; | 677 | continue; |
| 596 | set_speed(input_speed, argv[k], &mode); | 678 | } |
| 597 | speed_was_set = 1; | 679 | |
| 598 | require_set_attr = 1; | 680 | param = find_param(arg); |
| 599 | } else if (STREQ(argv[k], "ospeed")) { | 681 | if (param & param_need_arg) { |
| 600 | if (k == argc - 1) | 682 | ++k; |
| 601 | bb_error_msg_and_die(bb_msg_requires_arg, argv[k]); | 683 | } |
| 602 | ++k; | 684 | |
| 603 | set_speed(output_speed, argv[k], &mode); | 685 | switch (param) { |
| 604 | speed_was_set = 1; | ||
| 605 | require_set_attr = 1; | ||
| 606 | } | ||
| 607 | #ifdef TIOCGWINSZ | ||
| 608 | else if (STREQ(argv[k], "rows")) { | ||
| 609 | if (k == argc - 1) | ||
| 610 | bb_error_msg_and_die(bb_msg_requires_arg, argv[k]); | ||
| 611 | ++k; | ||
| 612 | set_window_size((int) bb_xparse_number(argv[k], stty_suffixes), | ||
| 613 | -1); | ||
| 614 | } else if (STREQ(argv[k], "cols") || STREQ(argv[k], "columns")) { | ||
| 615 | if (k == argc - 1) | ||
| 616 | bb_error_msg_and_die(bb_msg_requires_arg, argv[k]); | ||
| 617 | ++k; | ||
| 618 | set_window_size(-1, | ||
| 619 | (int) bb_xparse_number(argv[k], stty_suffixes)); | ||
| 620 | } else if (STREQ(argv[k], "size")) { | ||
| 621 | max_col = screen_columns(); | ||
| 622 | current_col = 0; | ||
| 623 | display_window_size(0); | ||
| 624 | } | ||
| 625 | #endif | ||
| 626 | #ifdef HAVE_C_LINE | 686 | #ifdef HAVE_C_LINE |
| 627 | else if (STREQ(argv[k], "line")) { | 687 | case param_line: |
| 628 | if (k == argc - 1) | 688 | mode.c_line = bb_xparse_number(argnext, stty_suffixes); |
| 629 | bb_error_msg_and_die(bb_msg_requires_arg, argv[k]); | 689 | require_set_attr = 1; |
| 630 | ++k; | 690 | break; |
| 631 | mode.c_line = bb_xparse_number(argv[k], stty_suffixes); | 691 | #endif |
| 632 | require_set_attr = 1; | 692 | #ifdef TIOCGWINSZ |
| 633 | } | 693 | case param_cols: |
| 694 | set_window_size(-1, (int) bb_xparse_number(argnext, stty_suffixes)); | ||
| 695 | break; | ||
| 696 | case param_size: | ||
| 697 | max_col = screen_columns(); | ||
| 698 | current_col = 0; | ||
| 699 | display_window_size(0); | ||
| 700 | break; | ||
| 701 | case param_rows: | ||
| 702 | set_window_size((int) bb_xparse_number(argnext, stty_suffixes), -1); | ||
| 703 | break; | ||
| 634 | #endif | 704 | #endif |
| 635 | else if (STREQ(argv[k], "speed")) { | 705 | case param_ispeed: |
| 636 | max_col = screen_columns(); | 706 | set_speed(input_speed, argnext, &mode); |
| 637 | display_speed(&mode, 0); | 707 | speed_was_set = 1; |
| 638 | } else if (recover_mode(argv[k], &mode) == 1) | 708 | require_set_attr = 1; |
| 709 | break; | ||
| 710 | case param_ospeed: | ||
| 711 | set_speed(output_speed, argnext, &mode); | ||
| 712 | speed_was_set = 1; | ||
| 713 | require_set_attr = 1; | ||
| 714 | break; | ||
| 715 | case param_speed: | ||
| 716 | max_col = screen_columns(); | ||
| 717 | display_speed(&mode, 0); | ||
| 718 | break; | ||
| 719 | default: | ||
| 720 | if (recover_mode(arg, &mode) == 1) | ||
| 639 | require_set_attr = 1; | 721 | require_set_attr = 1; |
| 640 | else if (string_to_baud(argv[k]) != (speed_t) - 1) { | 722 | else /* true: if (string_to_baud(arg) != (speed_t) -1) */ { |
| 641 | set_speed(both_speeds, argv[k], &mode); | 723 | set_speed(both_speeds, arg, &mode); |
| 642 | speed_was_set = 1; | 724 | speed_was_set = 1; |
| 643 | require_set_attr = 1; | 725 | require_set_attr = 1; |
| 644 | } else | 726 | } /* else - impossible (caught in the first pass): |
| 645 | bb_error_msg_and_die("invalid argument `%s'", argv[k]); | 727 | bb_error_msg_and_die("invalid argument '%s'", arg); */ |
| 646 | } | 728 | } |
| 647 | } | 729 | } |
| 648 | 730 | ||
| @@ -665,13 +747,6 @@ int stty_main(int argc, char **argv) | |||
| 665 | if (tcgetattr(STDIN_FILENO, &new_mode)) | 747 | if (tcgetattr(STDIN_FILENO, &new_mode)) |
| 666 | perror_on_device("%s"); | 748 | perror_on_device("%s"); |
| 667 | 749 | ||
| 668 | /* Normally, one shouldn't use memcmp to compare structures that | ||
| 669 | may have `holes' containing uninitialized data, but we have been | ||
| 670 | careful to initialize the storage of these two variables to all | ||
| 671 | zeroes. One might think it more efficient simply to compare the | ||
| 672 | modified fields, but that would require enumerating those fields -- | ||
| 673 | and not all systems have the same fields in this structure. */ | ||
| 674 | |||
| 675 | if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) { | 750 | if (memcmp(&mode, &new_mode, sizeof(mode)) != 0) { |
| 676 | #ifdef CIBAUD | 751 | #ifdef CIBAUD |
| 677 | /* SunOS 4.1.3 (at least) has the problem that after this sequence, | 752 | /* SunOS 4.1.3 (at least) has the problem that after this sequence, |
| @@ -695,14 +770,11 @@ int stty_main(int argc, char **argv) | |||
| 695 | 770 | ||
| 696 | /* Return 0 if not applied because not reversible; otherwise return 1. */ | 771 | /* Return 0 if not applied because not reversible; otherwise return 1. */ |
| 697 | 772 | ||
| 698 | static int | 773 | static void |
| 699 | set_mode(const struct mode_info *info, int reversed, struct termios *mode) | 774 | set_mode(const struct mode_info *info, int reversed, struct termios *mode) |
| 700 | { | 775 | { |
| 701 | tcflag_t *bitsp; | 776 | tcflag_t *bitsp; |
| 702 | 777 | ||
| 703 | if (reversed && (info->flags & REV) == 0) | ||
| 704 | return 0; | ||
| 705 | |||
| 706 | bitsp = mode_type_flag(EMT(info->type), mode); | 778 | bitsp = mode_type_flag(EMT(info->type), mode); |
| 707 | 779 | ||
| 708 | if (bitsp == NULL) { | 780 | if (bitsp == NULL) { |
| @@ -861,8 +933,6 @@ set_mode(const struct mode_info *info, int reversed, struct termios *mode) | |||
| 861 | *bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits; | 933 | *bitsp = *bitsp & ~((unsigned long)info->mask) & ~info->bits; |
| 862 | else | 934 | else |
| 863 | *bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits; | 935 | *bitsp = (*bitsp & ~((unsigned long)info->mask)) | info->bits; |
| 864 | |||
| 865 | return 1; | ||
| 866 | } | 936 | } |
| 867 | 937 | ||
| 868 | static void | 938 | static void |
| @@ -1179,7 +1249,7 @@ static void display_recoverable(struct termios *mode) | |||
| 1179 | putchar('\n'); | 1249 | putchar('\n'); |
| 1180 | } | 1250 | } |
| 1181 | 1251 | ||
| 1182 | static int recover_mode(char *arg, struct termios *mode) | 1252 | static int recover_mode(const char *arg, struct termios *mode) |
| 1183 | { | 1253 | { |
| 1184 | int i, n; | 1254 | int i, n; |
| 1185 | unsigned int chr; | 1255 | unsigned int chr; |
| @@ -1269,5 +1339,5 @@ static const char *visible(unsigned int ch) | |||
| 1269 | } | 1339 | } |
| 1270 | 1340 | ||
| 1271 | *bpout = '\0'; | 1341 | *bpout = '\0'; |
| 1272 | return (const char *) buf; | 1342 | return buf; |
| 1273 | } | 1343 | } |
