aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-02-16 13:19:19 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-02-16 13:19:19 +0000
commit1e18f1bab3400246129756a35bb5752ba98f4c90 (patch)
tree6932fa8833f66ef63098ff30d7093b74546a2c0b
parent284d0faed6a1ec2adcc4b7aea31ae3d05b3b70d9 (diff)
downloadbusybox-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.c199
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
653static struct interfaces_file_t *read_interfaces(const char *filename) 653static 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
958static int popen2(FILE **in, FILE **out, char *command, ...) 987static 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
1011static char *run_mapping(char *physical, struct mapping_defn_t * map) 1019static 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
1063static llist_t *find_iface_state(llist_t *state_list, const char *iface) 1063static 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;