diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-16 13:19:19 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-16 13:19:19 +0000 |
commit | 1e18f1bab3400246129756a35bb5752ba98f4c90 (patch) | |
tree | 6932fa8833f66ef63098ff30d7093b74546a2c0b | |
parent | 284d0faed6a1ec2adcc4b7aea31ae3d05b3b70d9 (diff) | |
download | busybox-w32-1e18f1bab3400246129756a35bb5752ba98f4c90.tar.gz busybox-w32-1e18f1bab3400246129756a35bb5752ba98f4c90.tar.bz2 busybox-w32-1e18f1bab3400246129756a35bb5752ba98f4c90.zip |
ifupdowm: shrink
ifupdown_main 2170 2459 +289
find_iface_state 57 56 -1
next_word 63 58 -5
popen2 350 - -350
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/2 up/down: 289/-356) Total: -67 bytes
-rw-r--r-- | networking/ifupdown.c | 199 |
1 files changed, 100 insertions, 99 deletions
diff --git a/networking/ifupdown.c b/networking/ifupdown.c index a794bf76a..d0d7bfe5b 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c | |||
@@ -590,8 +590,8 @@ static char *next_word(char **buf) | |||
590 | /* Skip over leading whitespace */ | 590 | /* Skip over leading whitespace */ |
591 | word = skip_whitespace(*buf); | 591 | word = skip_whitespace(*buf); |
592 | 592 | ||
593 | /* Stop on EOL/comments */ | 593 | /* Stop on EOL */ |
594 | if (*word == '#' || *word == '\0') | 594 | if (*word == '\0') |
595 | return NULL; | 595 | return NULL; |
596 | 596 | ||
597 | /* Find the length of this word (can't be 0) */ | 597 | /* Find the length of this word (can't be 0) */ |
@@ -652,40 +652,67 @@ static const llist_t *find_list_string(const llist_t *list, const char *string) | |||
652 | 652 | ||
653 | static struct interfaces_file_t *read_interfaces(const char *filename) | 653 | static struct interfaces_file_t *read_interfaces(const char *filename) |
654 | { | 654 | { |
655 | /* Let's try to be compatible. | ||
656 | * | ||
657 | * "man 5 interfaces" says: | ||
658 | * Lines starting with "#" are ignored. Note that end-of-line | ||
659 | * comments are NOT supported, comments must be on a line of their own. | ||
660 | * A line may be extended across multiple lines by making | ||
661 | * the last character a backslash. | ||
662 | * | ||
663 | * Seen elsewhere in example config file: | ||
664 | * A "#" character in the very first column makes the rest of the line | ||
665 | * be ignored. Blank lines are ignored. Lines may be indented freely. | ||
666 | * A "\" character at the very end of the line indicates the next line | ||
667 | * should be treated as a continuation of the current one. | ||
668 | */ | ||
655 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING | 669 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING |
656 | struct mapping_defn_t *currmap = NULL; | 670 | struct mapping_defn_t *currmap = NULL; |
657 | #endif | 671 | #endif |
658 | struct interface_defn_t *currif = NULL; | 672 | struct interface_defn_t *currif = NULL; |
659 | struct interfaces_file_t *defn; | 673 | struct interfaces_file_t *defn; |
660 | FILE *f; | 674 | FILE *f; |
661 | char *firstword; | ||
662 | char *buf; | 675 | char *buf; |
663 | 676 | char *first_word; | |
677 | char *rest_of_line; | ||
664 | enum { NONE, IFACE, MAPPING } currently_processing = NONE; | 678 | enum { NONE, IFACE, MAPPING } currently_processing = NONE; |
665 | 679 | ||
666 | defn = xzalloc(sizeof(struct interfaces_file_t)); | 680 | defn = xzalloc(sizeof(*defn)); |
667 | |||
668 | f = xfopen(filename, "r"); | 681 | f = xfopen(filename, "r"); |
669 | 682 | ||
670 | while ((buf = xmalloc_getline(f)) != NULL) { | 683 | while ((buf = xmalloc_getline(f)) != NULL) { |
671 | char *buf_ptr = buf; | 684 | #if ENABLE_DESKTOP |
672 | 685 | /* Trailing "\" concatenates lines */ | |
673 | firstword = next_word(&buf_ptr); | 686 | char *p; |
674 | if (firstword == NULL) { | 687 | while ((p = last_char_is(buf, '\\')) != NULL) { |
688 | *p = '\0'; | ||
689 | rest_of_line = xmalloc_getline(f); | ||
690 | if (!rest_of_line) | ||
691 | break; | ||
692 | p = xasprintf("%s%s", buf, rest_of_line); | ||
693 | free(buf); | ||
694 | free(rest_of_line); | ||
695 | buf = p; | ||
696 | } | ||
697 | #endif | ||
698 | rest_of_line = buf; | ||
699 | first_word = next_word(&rest_of_line); | ||
700 | if (!first_word || *buf == '#') { | ||
675 | free(buf); | 701 | free(buf); |
676 | continue; /* blank line */ | 702 | continue; /* blank/comment line */ |
677 | } | 703 | } |
678 | 704 | ||
679 | if (strcmp(firstword, "mapping") == 0) { | 705 | if (strcmp(first_word, "mapping") == 0) { |
680 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING | 706 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING |
681 | currmap = xzalloc(sizeof(*currmap)); | 707 | currmap = xzalloc(sizeof(*currmap)); |
682 | 708 | ||
683 | while ((firstword = next_word(&buf_ptr)) != NULL) { | 709 | while ((first_word = next_word(&rest_of_line)) != NULL) { |
684 | if (currmap->n_matches >= currmap->max_matches) { | 710 | if (currmap->n_matches >= currmap->max_matches) { |
685 | currmap->max_matches = currmap->max_matches * 2 + 1; | 711 | currmap->max_matches = currmap->max_matches * 2 + 1; |
686 | currmap->match = xrealloc(currmap->match, sizeof(*currmap->match) * currmap->max_matches); | 712 | currmap->match = xrealloc(currmap->match, |
713 | sizeof(*currmap->match) * currmap->max_matches); | ||
687 | } | 714 | } |
688 | currmap->match[currmap->n_matches++] = xstrdup(firstword); | 715 | currmap->match[currmap->n_matches++] = xstrdup(first_word); |
689 | } | 716 | } |
690 | /*currmap->max_mappings = 0; - done by xzalloc */ | 717 | /*currmap->max_mappings = 0; - done by xzalloc */ |
691 | /*currmap->n_mappings = 0;*/ | 718 | /*currmap->n_mappings = 0;*/ |
@@ -702,7 +729,7 @@ static struct interfaces_file_t *read_interfaces(const char *filename) | |||
702 | debug_noise("Added mapping\n"); | 729 | debug_noise("Added mapping\n"); |
703 | #endif | 730 | #endif |
704 | currently_processing = MAPPING; | 731 | currently_processing = MAPPING; |
705 | } else if (strcmp(firstword, "iface") == 0) { | 732 | } else if (strcmp(first_word, "iface") == 0) { |
706 | static const struct address_family_t *const addr_fams[] = { | 733 | static const struct address_family_t *const addr_fams[] = { |
707 | #if ENABLE_FEATURE_IFUPDOWN_IPV4 | 734 | #if ENABLE_FEATURE_IFUPDOWN_IPV4 |
708 | &addr_inet, | 735 | &addr_inet, |
@@ -712,24 +739,23 @@ static struct interfaces_file_t *read_interfaces(const char *filename) | |||
712 | #endif | 739 | #endif |
713 | NULL | 740 | NULL |
714 | }; | 741 | }; |
715 | |||
716 | char *iface_name; | 742 | char *iface_name; |
717 | char *address_family_name; | 743 | char *address_family_name; |
718 | char *method_name; | 744 | char *method_name; |
719 | llist_t *iface_list; | 745 | llist_t *iface_list; |
720 | 746 | ||
721 | currif = xzalloc(sizeof(*currif)); | 747 | currif = xzalloc(sizeof(*currif)); |
722 | iface_name = next_word(&buf_ptr); | 748 | iface_name = next_word(&rest_of_line); |
723 | address_family_name = next_word(&buf_ptr); | 749 | address_family_name = next_word(&rest_of_line); |
724 | method_name = next_word(&buf_ptr); | 750 | method_name = next_word(&rest_of_line); |
725 | 751 | ||
726 | if (method_name == NULL) | 752 | if (method_name == NULL) |
727 | bb_error_msg_and_die("too few parameters for line \"%s\"", buf); | 753 | bb_error_msg_and_die("too few parameters for line \"%s\"", buf); |
728 | 754 | ||
729 | /* ship any trailing whitespace */ | 755 | /* ship any trailing whitespace */ |
730 | buf_ptr = skip_whitespace(buf_ptr); | 756 | rest_of_line = skip_whitespace(rest_of_line); |
731 | 757 | ||
732 | if (buf_ptr[0] != '\0' /* && buf_ptr[0] != '#' */) | 758 | if (rest_of_line[0] != '\0' /* && rest_of_line[0] != '#' */) |
733 | bb_error_msg_and_die("too many parameters \"%s\"", buf); | 759 | bb_error_msg_and_die("too many parameters \"%s\"", buf); |
734 | 760 | ||
735 | currif->iface = xstrdup(iface_name); | 761 | currif->iface = xstrdup(iface_name); |
@@ -754,57 +780,59 @@ static struct interfaces_file_t *read_interfaces(const char *filename) | |||
754 | 780 | ||
755 | debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name); | 781 | debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name); |
756 | currently_processing = IFACE; | 782 | currently_processing = IFACE; |
757 | } else if (strcmp(firstword, "auto") == 0) { | 783 | } else if (strcmp(first_word, "auto") == 0) { |
758 | while ((firstword = next_word(&buf_ptr)) != NULL) { | 784 | while ((first_word = next_word(&rest_of_line)) != NULL) { |
759 | 785 | ||
760 | /* Check the interface isnt already listed */ | 786 | /* Check the interface isnt already listed */ |
761 | if (find_list_string(defn->autointerfaces, firstword)) { | 787 | if (find_list_string(defn->autointerfaces, first_word)) { |
762 | bb_perror_msg_and_die("interface declared auto twice \"%s\"", buf); | 788 | bb_perror_msg_and_die("interface declared auto twice \"%s\"", buf); |
763 | } | 789 | } |
764 | 790 | ||
765 | /* Add the interface to the list */ | 791 | /* Add the interface to the list */ |
766 | llist_add_to_end(&(defn->autointerfaces), xstrdup(firstword)); | 792 | llist_add_to_end(&(defn->autointerfaces), xstrdup(first_word)); |
767 | debug_noise("\nauto %s\n", firstword); | 793 | debug_noise("\nauto %s\n", first_word); |
768 | } | 794 | } |
769 | currently_processing = NONE; | 795 | currently_processing = NONE; |
770 | } else { | 796 | } else { |
771 | switch (currently_processing) { | 797 | switch (currently_processing) { |
772 | case IFACE: | 798 | case IFACE: |
773 | if (buf_ptr[0] == '\0') | 799 | if (rest_of_line[0] == '\0') |
774 | bb_error_msg_and_die("option with empty value \"%s\"", buf); | 800 | bb_error_msg_and_die("option with empty value \"%s\"", buf); |
775 | 801 | ||
776 | if (strcmp(firstword, "up") != 0 | 802 | if (strcmp(first_word, "up") != 0 |
777 | && strcmp(firstword, "down") != 0 | 803 | && strcmp(first_word, "down") != 0 |
778 | && strcmp(firstword, "pre-up") != 0 | 804 | && strcmp(first_word, "pre-up") != 0 |
779 | && strcmp(firstword, "post-down") != 0 | 805 | && strcmp(first_word, "post-down") != 0 |
780 | ) { | 806 | ) { |
781 | int i; | 807 | int i; |
782 | for (i = 0; i < currif->n_options; i++) { | 808 | for (i = 0; i < currif->n_options; i++) { |
783 | if (strcmp(currif->option[i].name, firstword) == 0) | 809 | if (strcmp(currif->option[i].name, first_word) == 0) |
784 | bb_error_msg_and_die("duplicate option \"%s\"", buf); | 810 | bb_error_msg_and_die("duplicate option \"%s\"", buf); |
785 | } | 811 | } |
786 | } | 812 | } |
787 | if (currif->n_options >= currif->max_options) { | 813 | if (currif->n_options >= currif->max_options) { |
788 | currif->max_options += 10; | 814 | currif->max_options += 10; |
789 | currif->option = xrealloc(currif->option, sizeof(*currif->option) * currif->max_options); | 815 | currif->option = xrealloc(currif->option, |
816 | sizeof(*currif->option) * currif->max_options); | ||
790 | } | 817 | } |
791 | debug_noise("\t%s=%s\n", firstword, buf_ptr); | 818 | debug_noise("\t%s=%s\n", first_word, rest_of_line); |
792 | currif->option[currif->n_options].name = xstrdup(firstword); | 819 | currif->option[currif->n_options].name = xstrdup(first_word); |
793 | currif->option[currif->n_options].value = xstrdup(buf_ptr); | 820 | currif->option[currif->n_options].value = xstrdup(rest_of_line); |
794 | currif->n_options++; | 821 | currif->n_options++; |
795 | break; | 822 | break; |
796 | case MAPPING: | 823 | case MAPPING: |
797 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING | 824 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING |
798 | if (strcmp(firstword, "script") == 0) { | 825 | if (strcmp(first_word, "script") == 0) { |
799 | if (currmap->script != NULL) | 826 | if (currmap->script != NULL) |
800 | bb_error_msg_and_die("duplicate script in mapping \"%s\"", buf); | 827 | bb_error_msg_and_die("duplicate script in mapping \"%s\"", buf); |
801 | currmap->script = xstrdup(next_word(&buf_ptr)); | 828 | currmap->script = xstrdup(next_word(&rest_of_line)); |
802 | } else if (strcmp(firstword, "map") == 0) { | 829 | } else if (strcmp(first_word, "map") == 0) { |
803 | if (currmap->n_mappings >= currmap->max_mappings) { | 830 | if (currmap->n_mappings >= currmap->max_mappings) { |
804 | currmap->max_mappings = currmap->max_mappings * 2 + 1; | 831 | currmap->max_mappings = currmap->max_mappings * 2 + 1; |
805 | currmap->mapping = xrealloc(currmap->mapping, sizeof(char *) * currmap->max_mappings); | 832 | currmap->mapping = xrealloc(currmap->mapping, |
833 | sizeof(char *) * currmap->max_mappings); | ||
806 | } | 834 | } |
807 | currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&buf_ptr)); | 835 | currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&rest_of_line)); |
808 | currmap->n_mappings++; | 836 | currmap->n_mappings++; |
809 | } else { | 837 | } else { |
810 | bb_error_msg_and_die("misplaced option \"%s\"", buf); | 838 | bb_error_msg_and_die("misplaced option \"%s\"", buf); |
@@ -817,7 +845,8 @@ static struct interfaces_file_t *read_interfaces(const char *filename) | |||
817 | } | 845 | } |
818 | } | 846 | } |
819 | free(buf); | 847 | free(buf); |
820 | } | 848 | } /* while (fgets) */ |
849 | |||
821 | if (ferror(f) != 0) { | 850 | if (ferror(f) != 0) { |
822 | /* ferror does NOT set errno! */ | 851 | /* ferror does NOT set errno! */ |
823 | bb_error_msg_and_die("%s: I/O error", filename); | 852 | bb_error_msg_and_die("%s: I/O error", filename); |
@@ -955,60 +984,39 @@ static int iface_down(struct interface_defn_t *iface) | |||
955 | } | 984 | } |
956 | 985 | ||
957 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING | 986 | #if ENABLE_FEATURE_IFUPDOWN_MAPPING |
958 | static int popen2(FILE **in, FILE **out, char *command, ...) | 987 | static int popen2(FILE **in, FILE **out, char *command, char *param) |
959 | { | 988 | { |
960 | va_list ap; | 989 | char *argv[3] = { command, param, NULL }; |
961 | char *argv[11] = { command }; | ||
962 | int argc; | ||
963 | int infd[2], outfd[2]; | 990 | int infd[2], outfd[2]; |
964 | pid_t pid; | 991 | pid_t pid; |
965 | 992 | ||
966 | argc = 1; | 993 | xpipe(infd); |
967 | va_start(ap, command); | 994 | xpipe(outfd); |
968 | while ((argc < 10) && (argv[argc] = va_arg(ap, char *))) { | ||
969 | argc++; | ||
970 | } | ||
971 | argv[argc] = NULL; /* make sure */ | ||
972 | va_end(ap); | ||
973 | |||
974 | if (pipe(infd) != 0) { | ||
975 | return 0; | ||
976 | } | ||
977 | |||
978 | if (pipe(outfd) != 0) { | ||
979 | close(infd[0]); | ||
980 | close(infd[1]); | ||
981 | return 0; | ||
982 | } | ||
983 | 995 | ||
984 | fflush(NULL); | 996 | fflush(NULL); |
985 | switch (pid = fork()) { | 997 | pid = fork(); |
986 | case -1: /* failure */ | 998 | |
987 | close(infd[0]); | 999 | switch (pid) { |
988 | close(infd[1]); | 1000 | case -1: /* failure */ |
989 | close(outfd[0]); | 1001 | bb_perror_msg_and_die("fork"); |
990 | close(outfd[1]); | 1002 | case 0: /* child */ |
991 | return 0; | 1003 | /* NB: close _first_, then move fds! */ |
992 | case 0: /* child */ | ||
993 | dup2(infd[0], 0); | ||
994 | dup2(outfd[1], 1); | ||
995 | close(infd[0]); | ||
996 | close(infd[1]); | 1004 | close(infd[1]); |
997 | close(outfd[0]); | 1005 | close(outfd[0]); |
998 | close(outfd[1]); | 1006 | xmove_fd(infd[0], 0); |
1007 | xmove_fd(outfd[1], 1); | ||
999 | BB_EXECVP(command, argv); | 1008 | BB_EXECVP(command, argv); |
1000 | exit(127); | 1009 | _exit(127); |
1001 | default: /* parent */ | ||
1002 | *in = fdopen(infd[1], "w"); | ||
1003 | *out = fdopen(outfd[0], "r"); | ||
1004 | close(infd[0]); | ||
1005 | close(outfd[1]); | ||
1006 | return pid; | ||
1007 | } | 1010 | } |
1008 | /* unreached */ | 1011 | /* parent */ |
1012 | close(infd[0]); | ||
1013 | close(outfd[1]); | ||
1014 | *in = fdopen(infd[1], "w"); | ||
1015 | *out = fdopen(outfd[0], "r"); | ||
1016 | return pid; | ||
1009 | } | 1017 | } |
1010 | 1018 | ||
1011 | static char *run_mapping(char *physical, struct mapping_defn_t * map) | 1019 | static char *run_mapping(char *physical, struct mapping_defn_t *map) |
1012 | { | 1020 | { |
1013 | FILE *in, *out; | 1021 | FILE *in, *out; |
1014 | int i, status; | 1022 | int i, status; |
@@ -1016,12 +1024,8 @@ static char *run_mapping(char *physical, struct mapping_defn_t * map) | |||
1016 | 1024 | ||
1017 | char *logical = xstrdup(physical); | 1025 | char *logical = xstrdup(physical); |
1018 | 1026 | ||
1019 | /* Run the mapping script. */ | 1027 | /* Run the mapping script. Never fails. */ |
1020 | pid = popen2(&in, &out, map->script, physical, NULL); | 1028 | pid = popen2(&in, &out, map->script, physical); |
1021 | |||
1022 | /* popen2() returns 0 on failure. */ | ||
1023 | if (pid == 0) | ||
1024 | return logical; | ||
1025 | 1029 | ||
1026 | /* Write mappings to stdin of mapping script. */ | 1030 | /* Write mappings to stdin of mapping script. */ |
1027 | for (i = 0; i < map->n_mappings; i++) { | 1031 | for (i = 0; i < map->n_mappings; i++) { |
@@ -1034,9 +1038,9 @@ static char *run_mapping(char *physical, struct mapping_defn_t * map) | |||
1034 | /* If the mapping script exited successfully, try to | 1038 | /* If the mapping script exited successfully, try to |
1035 | * grab a line of output and use that as the name of the | 1039 | * grab a line of output and use that as the name of the |
1036 | * logical interface. */ | 1040 | * logical interface. */ |
1037 | char *new_logical = xmalloc(MAX_INTERFACE_LENGTH); | 1041 | char *new_logical = xmalloc_getline(out); |
1038 | 1042 | ||
1039 | if (fgets(new_logical, MAX_INTERFACE_LENGTH, out)) { | 1043 | if (new_logical) { |
1040 | /* If we are able to read a line of output from the script, | 1044 | /* If we are able to read a line of output from the script, |
1041 | * remove any trailing whitespace and use this value | 1045 | * remove any trailing whitespace and use this value |
1042 | * as the name of the logical interface. */ | 1046 | * as the name of the logical interface. */ |
@@ -1047,10 +1051,6 @@ static char *run_mapping(char *physical, struct mapping_defn_t * map) | |||
1047 | 1051 | ||
1048 | free(logical); | 1052 | free(logical); |
1049 | logical = new_logical; | 1053 | logical = new_logical; |
1050 | } else { | ||
1051 | /* If we are UNABLE to read a line of output, discard our | ||
1052 | * freshly allocated memory. */ | ||
1053 | free(new_logical); | ||
1054 | } | 1054 | } |
1055 | } | 1055 | } |
1056 | 1056 | ||
@@ -1062,12 +1062,13 @@ static char *run_mapping(char *physical, struct mapping_defn_t * map) | |||
1062 | 1062 | ||
1063 | static llist_t *find_iface_state(llist_t *state_list, const char *iface) | 1063 | static llist_t *find_iface_state(llist_t *state_list, const char *iface) |
1064 | { | 1064 | { |
1065 | unsigned short iface_len = strlen(iface); | 1065 | unsigned iface_len = strlen(iface); |
1066 | llist_t *search = state_list; | 1066 | llist_t *search = state_list; |
1067 | 1067 | ||
1068 | while (search) { | 1068 | while (search) { |
1069 | if ((strncmp(search->data, iface, iface_len) == 0) | 1069 | if ((strncmp(search->data, iface, iface_len) == 0) |
1070 | && (search->data[iface_len] == '=')) { | 1070 | && (search->data[iface_len] == '=') |
1071 | ) { | ||
1071 | return search; | 1072 | return search; |
1072 | } | 1073 | } |
1073 | search = search->link; | 1074 | search = search->link; |