aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Kbuild.src56
-rw-r--r--libbb/appletlib.c192
-rw-r--r--libbb/bb_qsort.c12
-rw-r--r--libbb/compare_string_array.c41
-rw-r--r--libbb/copy_file.c6
-rw-r--r--libbb/executable.c14
-rw-r--r--libbb/find_mount_point.c45
-rw-r--r--libbb/find_pid_by_name.c6
-rw-r--r--libbb/get_last_path_component.c28
-rw-r--r--libbb/get_line_from_file.c4
-rw-r--r--libbb/human_readable.c6
-rw-r--r--libbb/inode_hash.c5
-rw-r--r--libbb/lineedit.c107
-rw-r--r--libbb/make_directory.c29
-rw-r--r--libbb/messages.c2
-rw-r--r--libbb/mode_string.c2
-rw-r--r--libbb/printable_string.c2
-rw-r--r--libbb/procps.c3
-rw-r--r--libbb/read_printf.c5
-rw-r--r--libbb/u_signal_names.c4
-rw-r--r--libbb/vfork_daemon_rexec.c6
-rw-r--r--libbb/xatonum_template.c5
-rw-r--r--libbb/xconnect.c14
-rw-r--r--libbb/xfuncs.c4
-rw-r--r--libbb/xfuncs_printf.c2
-rw-r--r--libbb/xreadlink.c2
26 files changed, 554 insertions, 48 deletions
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 8c9ba8cca..799f6d01a 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -12,14 +12,11 @@ INSERT
12 12
13lib-y += appletlib.o 13lib-y += appletlib.o
14lib-y += ask_confirmation.o 14lib-y += ask_confirmation.o
15lib-y += bb_askpass.o
16lib-y += bb_bswap_64.o 15lib-y += bb_bswap_64.o
17lib-y += bb_do_delay.o
18lib-y += bb_pwd.o 16lib-y += bb_pwd.o
19lib-y += bb_qsort.o 17lib-y += bb_qsort.o
20#lib-y += bb_strtod.o 18#lib-y += bb_strtod.o
21lib-y += bb_strtonum.o 19lib-y += bb_strtonum.o
22lib-y += change_identity.o
23lib-y += chomp.o 20lib-y += chomp.o
24lib-y += compare_string_array.o 21lib-y += compare_string_array.o
25lib-y += concat_path_file.o 22lib-y += concat_path_file.o
@@ -28,32 +25,23 @@ lib-y += copy_file.o
28lib-y += copyfd.o 25lib-y += copyfd.o
29lib-y += crc32.o 26lib-y += crc32.o
30lib-y += default_error_retval.o 27lib-y += default_error_retval.o
31lib-y += device_open.o
32lib-y += dump.o 28lib-y += dump.o
33lib-y += executable.o 29lib-y += executable.o
34lib-y += fclose_nonstdin.o 30lib-y += fclose_nonstdin.o
35lib-y += fflush_stdout_and_exit.o 31lib-y += fflush_stdout_and_exit.o
36lib-y += fgets_str.o 32lib-y += fgets_str.o
37lib-y += find_pid_by_name.o 33lib-y += find_pid_by_name.o
38lib-y += find_root_device.o
39lib-y += full_write.o 34lib-y += full_write.o
40lib-y += get_console.o
41lib-y += get_last_path_component.o 35lib-y += get_last_path_component.o
42lib-y += get_line_from_file.o 36lib-y += get_line_from_file.o
43lib-y += getpty.o 37lib-y += getopt32.o
44lib-y += get_volsize.o
45lib-y += herror_msg.o 38lib-y += herror_msg.o
46lib-y += human_readable.o 39lib-y += human_readable.o
47lib-y += inet_common.o
48lib-y += inode_hash.o
49lib-y += isdirectory.o 40lib-y += isdirectory.o
50lib-y += kernel_version.o
51lib-y += last_char_is.o 41lib-y += last_char_is.o
52lib-y += lineedit.o lineedit_ptr_hack.o 42lib-y += lineedit.o lineedit_ptr_hack.o
53lib-y += llist.o 43lib-y += llist.o
54lib-y += login.o
55lib-y += make_directory.o 44lib-y += make_directory.o
56lib-y += makedev.o
57lib-y += hash_md5_sha.o 45lib-y += hash_md5_sha.o
58# Alternative (disabled) MD5 implementation 46# Alternative (disabled) MD5 implementation
59#lib-y += hash_md5prime.o 47#lib-y += hash_md5prime.o
@@ -61,20 +49,15 @@ lib-y += messages.o
61lib-y += mode_string.o 49lib-y += mode_string.o
62lib-y += parse_mode.o 50lib-y += parse_mode.o
63lib-y += perror_msg.o 51lib-y += perror_msg.o
64lib-y += perror_nomsg.o
65lib-y += perror_nomsg_and_die.o 52lib-y += perror_nomsg_and_die.o
66lib-y += pidfile.o
67lib-y += platform.o 53lib-y += platform.o
68lib-y += printable.o 54lib-y += printable.o
69lib-y += printable_string.o 55lib-y += printable_string.o
70lib-y += print_flags.o
71lib-y += process_escape_sequence.o 56lib-y += process_escape_sequence.o
72lib-y += procps.o 57lib-y += procps.o
73lib-y += progress.o
74lib-y += ptr_to_globals.o 58lib-y += ptr_to_globals.o
75lib-y += read.o 59lib-y += read.o
76lib-y += read_printf.o 60lib-y += read_printf.o
77lib-y += read_key.o
78lib-y += recursive_action.o 61lib-y += recursive_action.o
79lib-y += remove_file.o 62lib-y += remove_file.o
80lib-y += run_shell.o 63lib-y += run_shell.o
@@ -83,12 +66,8 @@ lib-y += safe_poll.o
83lib-y += safe_strncpy.o 66lib-y += safe_strncpy.o
84lib-y += safe_write.o 67lib-y += safe_write.o
85lib-y += securetty.o 68lib-y += securetty.o
86lib-y += setup_environment.o
87lib-y += signals.o
88lib-y += simplify_path.o
89lib-y += single_argv.o 69lib-y += single_argv.o
90lib-y += skip_whitespace.o 70lib-y += skip_whitespace.o
91lib-y += speed_table.o
92lib-y += str_tolower.o 71lib-y += str_tolower.o
93lib-y += strrstr.o 72lib-y += strrstr.o
94lib-y += sysconf.o 73lib-y += sysconf.o
@@ -98,20 +77,45 @@ lib-y += u_signal_names.o
98lib-y += uuencode.o 77lib-y += uuencode.o
99lib-y += verror_msg.o 78lib-y += verror_msg.o
100lib-y += vfork_daemon_rexec.o 79lib-y += vfork_daemon_rexec.o
101lib-y += warn_ignoring_args.o
102lib-y += wfopen.o 80lib-y += wfopen.o
103lib-y += wfopen_input.o 81lib-y += wfopen_input.o
104lib-y += write.o
105lib-y += xatonum.o 82lib-y += xatonum.o
106lib-y += xconnect.o 83lib-y += xconnect.o
107lib-y += xfuncs.o 84lib-y += xfuncs.o
108lib-y += xfuncs_printf.o 85lib-y += xfuncs_printf.o
109lib-y += xfunc_die.o 86lib-y += xfunc_die.o
110lib-y += xgetcwd.o 87lib-y += xgetcwd.o
111lib-y += xgethostbyname.o
112lib-y += xreadlink.o 88lib-y += xreadlink.o
113lib-y += xrealloc_vector.o 89lib-y += xrealloc_vector.o
114 90
91lib-$(CONFIG_PLATFORM_POSIX) += bb_askpass.o
92lib-$(CONFIG_PLATFORM_POSIX) += bb_do_delay.o
93lib-$(CONFIG_PLATFORM_POSIX) += change_identity.o
94lib-$(CONFIG_PLATFORM_POSIX) += device_open.o
95lib-$(CONFIG_PLATFORM_POSIX) += find_root_device.o
96lib-$(CONFIG_PLATFORM_POSIX) += get_console.o
97lib-$(CONFIG_PLATFORM_POSIX) += getpty.o
98lib-$(CONFIG_PLATFORM_POSIX) += get_volsize.o
99lib-$(CONFIG_PLATFORM_POSIX) += inet_common.o
100lib-$(CONFIG_PLATFORM_POSIX) += inode_hash.o
101lib-$(CONFIG_FEATURE_EXTRA_FILE_DATA) += inode_hash.o
102lib-$(CONFIG_PLATFORM_POSIX) += kernel_version.o
103lib-$(CONFIG_PLATFORM_POSIX) += login.o
104lib-$(CONFIG_PLATFORM_POSIX) += makedev.o
105lib-$(CONFIG_PLATFORM_POSIX) += perror_nomsg.o
106lib-$(CONFIG_PLATFORM_POSIX) += pidfile.o
107lib-$(CONFIG_PLATFORM_POSIX) += print_flags.o
108lib-$(CONFIG_PLATFORM_POSIX) += progress.o
109lib-$(CONFIG_PLATFORM_POSIX) += read_key.o
110lib-$(CONFIG_PLATFORM_POSIX) += setup_environment.o
111lib-$(CONFIG_PLATFORM_POSIX) += signals.o
112lib-$(CONFIG_PLATFORM_POSIX) += simplify_path.o
113lib-$(CONFIG_PLATFORM_POSIX) += speed_table.o
114lib-$(CONFIG_PLATFORM_POSIX) += udp_io.o
115lib-$(CONFIG_PLATFORM_POSIX) += warn_ignoring_args.o
116lib-$(CONFIG_PLATFORM_POSIX) += write.o
117lib-$(CONFIG_PLATFORM_POSIX) += xgethostbyname.o
118
115lib-$(CONFIG_PLATFORM_LINUX) += match_fstype.o 119lib-$(CONFIG_PLATFORM_LINUX) += match_fstype.o
116 120
117lib-$(CONFIG_FEATURE_UTMP) += utmp.o 121lib-$(CONFIG_FEATURE_UTMP) += utmp.o
@@ -123,7 +127,7 @@ lib-$(CONFIG_FEATURE_MTAB_SUPPORT) += mtab.o
123lib-$(CONFIG_UNICODE_SUPPORT) += unicode.o 127lib-$(CONFIG_UNICODE_SUPPORT) += unicode.o
124lib-$(CONFIG_FEATURE_CHECK_NAMES) += die_if_bad_username.o 128lib-$(CONFIG_FEATURE_CHECK_NAMES) += die_if_bad_username.o
125 129
126lib-$(CONFIG_NC) += udp_io.o 130lib-$(CONFIG_NC_110_COMPAT) += udp_io.o
127lib-$(CONFIG_NETCAT) += udp_io.o 131lib-$(CONFIG_NETCAT) += udp_io.o
128lib-$(CONFIG_DNSD) += udp_io.o 132lib-$(CONFIG_DNSD) += udp_io.o
129lib-$(CONFIG_NTPD) += udp_io.o 133lib-$(CONFIG_NTPD) += udp_io.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index c15014a34..35aabe758 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -48,6 +48,15 @@
48# define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__ 48# define IF_FEATURE_INDIVIDUAL(...) __VA_ARGS__
49#endif 49#endif
50 50
51#if (ENABLE_FEATURE_INSTALLER && !ENABLE_PLATFORM_MINGW32) || \
52 (ENABLE_PLATFORM_MINGW32 && (ENABLE_FEATURE_PREFER_APPLETS \
53 || ENABLE_FEATURE_SH_STANDALONE \
54 || ENABLE_FEATURE_SH_NOFORK))
55# define IF_FULL_LIST_OPTION(...) __VA_ARGS__
56#else
57# define IF_FULL_LIST_OPTION(...)
58#endif
59
51#include "usage_compressed.h" 60#include "usage_compressed.h"
52 61
53#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS 62#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
@@ -57,6 +66,7 @@
57# define NUM_SCRIPTS 0 66# define NUM_SCRIPTS 0
58#endif 67#endif
59#if NUM_SCRIPTS > 0 68#if NUM_SCRIPTS > 0
69# define BB_ARCHIVE_PUBLIC
60# include "bb_archive.h" 70# include "bb_archive.h"
61static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS }; 71static const char packed_scripts[] ALIGN1 = { PACKED_SCRIPTS };
62#endif 72#endif
@@ -106,6 +116,7 @@ static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
106#if ENABLE_FEATURE_COMPRESS_USAGE 116#if ENABLE_FEATURE_COMPRESS_USAGE
107 117
108static const char packed_usage[] ALIGN1 = { PACKED_USAGE }; 118static const char packed_usage[] ALIGN1 = { PACKED_USAGE };
119# define BB_ARCHIVE_PUBLIC
109# include "bb_archive.h" 120# include "bb_archive.h"
110# define unpack_usage_messages() \ 121# define unpack_usage_messages() \
111 unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE)) 122 unpack_bz2_data(packed_usage, sizeof(packed_usage), sizeof(UNPACKED_USAGE))
@@ -149,7 +160,11 @@ void FAST_FUNC bb_show_usage(void)
149 ap--; 160 ap--;
150 } 161 }
151 full_write2_str(bb_banner); 162 full_write2_str(bb_banner);
163#if ENABLE_PLATFORM_MINGW32
164 full_write2_str(" multi-call binary\n");
165#else
152 full_write2_str(" multi-call binary.\n"); /* common string */ 166 full_write2_str(" multi-call binary.\n"); /* common string */
167#endif
153 if (*p == '\b') 168 if (*p == '\b')
154 full_write2_str("\nNo help available\n"); 169 full_write2_str("\nNo help available\n");
155 else { 170 else {
@@ -312,6 +327,10 @@ void lbb_prepare(const char *applet
312 if (ENABLE_LOCALE_SUPPORT) 327 if (ENABLE_LOCALE_SUPPORT)
313 setlocale(LC_ALL, ""); 328 setlocale(LC_ALL, "");
314 329
330#if ENABLE_PLATFORM_MINGW32
331 init_winsock();
332#endif
333
315#if ENABLE_FEATURE_INDIVIDUAL 334#if ENABLE_FEATURE_INDIVIDUAL
316 /* Redundant for busybox (run_applet_and_exit covers that case) 335 /* Redundant for busybox (run_applet_and_exit covers that case)
317 * but needed for "individual applet" mode */ 336 * but needed for "individual applet" mode */
@@ -702,6 +721,7 @@ static void check_suid(int applet_no)
702 721
703 722
704# if ENABLE_FEATURE_INSTALLER 723# if ENABLE_FEATURE_INSTALLER
724# if !ENABLE_PLATFORM_MINGW32
705static const char usr_bin [] ALIGN1 = "/usr/bin/"; 725static const char usr_bin [] ALIGN1 = "/usr/bin/";
706static const char usr_sbin[] ALIGN1 = "/usr/sbin/"; 726static const char usr_sbin[] ALIGN1 = "/usr/sbin/";
707static const char *const install_dir[] = { 727static const char *const install_dir[] = {
@@ -746,6 +766,30 @@ static void install_links(const char *busybox, int use_symbolic_links,
746 continue; 766 continue;
747 } 767 }
748} 768}
769# else /* ENABLE_PLATFORM_MINGW32 */
770static void install_links(const char *busybox,
771 int use_symbolic_links UNUSED_PARAM, char *custom_install_dir)
772{
773 char *fpc;
774 const char *appname = applet_names;
775 int rc;
776
777 if (!is_directory(custom_install_dir, FALSE))
778 bb_error_msg_and_die("'%s' is not a directory", custom_install_dir);
779
780 while (*appname) {
781 fpc = xasprintf("%s/%s.exe", custom_install_dir, appname);
782 rc = link(busybox, fpc);
783 if (rc != 0 && (errno != EEXIST ||
784 strcmp("busybox.exe", bb_basename(fpc)) != 0)) {
785 bb_simple_perror_msg(fpc);
786 }
787 free(fpc);
788 while (*appname++ != '\0')
789 continue;
790 }
791}
792# endif
749# elif ENABLE_BUSYBOX 793# elif ENABLE_BUSYBOX
750static void install_links(const char *busybox UNUSED_PARAM, 794static void install_links(const char *busybox UNUSED_PARAM,
751 int use_symbolic_links UNUSED_PARAM, 795 int use_symbolic_links UNUSED_PARAM,
@@ -829,20 +873,35 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
829 873
830 dup2(1, 2); 874 dup2(1, 2);
831 full_write2_str(bb_banner); /* reuse const string */ 875 full_write2_str(bb_banner); /* reuse const string */
876#if ENABLE_PLATFORM_MINGW32
877 full_write2_str(" multi-call binary\n"); /* reuse */
878#else
832 full_write2_str(" multi-call binary.\n"); /* reuse */ 879 full_write2_str(" multi-call binary.\n"); /* reuse */
880#endif
881#if defined(MINGW_VER)
882 if (sizeof(MINGW_VER) > 5) {
883 full_write2_str(MINGW_VER "\n\n");
884 }
885#endif
833 full_write2_str( 886 full_write2_str(
834 "BusyBox is copyrighted by many authors between 1998-2015.\n" 887 "BusyBox is copyrighted by many authors between 1998-2019.\n"
835 "Licensed under GPLv2. See source distribution for detailed\n" 888 "Licensed under GPLv2. See source distribution for detailed\n"
836 "copyright notices.\n" 889 "copyright notices.\n"
837 "\n" 890 "\n"
838 "Usage: busybox [function [arguments]...]\n" 891 "Usage: busybox [function [arguments]...]\n"
839 " or: busybox --list"IF_FEATURE_INSTALLER("[-full]")"\n" 892 " or: busybox --list"IF_FULL_LIST_OPTION("[-full]")"\n"
840# if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0 893# if ENABLE_FEATURE_SHOW_SCRIPT && NUM_SCRIPTS > 0
841 " or: busybox --show SCRIPT\n" 894 " or: busybox --show SCRIPT\n"
842# endif 895# endif
843 IF_FEATURE_INSTALLER( 896 IF_FEATURE_INSTALLER(
897 IF_NOT_PLATFORM_MINGW32(
844 " or: busybox --install [-s] [DIR]\n" 898 " or: busybox --install [-s] [DIR]\n"
845 ) 899 )
900 IF_PLATFORM_MINGW32(
901 " or: busybox --install [DIR]\n"
902 " or: busybox --uninstall [-n] file\n"
903 )
904 )
846 " or: function [arguments]...\n" 905 " or: function [arguments]...\n"
847 "\n" 906 "\n"
848 IF_NOT_FEATURE_SH_STANDALONE( 907 IF_NOT_FEATURE_SH_STANDALONE(
@@ -859,6 +918,11 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
859 "\tTo run external program, use full path (/sbin/ip instead of ip).\n" 918 "\tTo run external program, use full path (/sbin/ip instead of ip).\n"
860 ) 919 )
861 "\n" 920 "\n"
921#if ENABLE_GLOBBING
922 "\tSupport for native Windows wildcards is enabled. In some\n"
923 "\tcases this may result in wildcards being processed twice.\n"
924 "\n"
925#endif
862 "Currently defined functions:\n" 926 "Currently defined functions:\n"
863 ); 927 );
864 col = 0; 928 col = 0;
@@ -903,9 +967,27 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
903 const char *a = applet_names; 967 const char *a = applet_names;
904 dup2(1, 2); 968 dup2(1, 2);
905 while (*a) { 969 while (*a) {
906# if ENABLE_FEATURE_INSTALLER 970# if ENABLE_FEATURE_INSTALLER && !ENABLE_PLATFORM_MINGW32
907 if (argv[1][6]) /* --list-full? */ 971 if (argv[1][6]) /* --list-full? */
908 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); 972 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1);
973# elif ENABLE_PLATFORM_MINGW32 && (ENABLE_FEATURE_PREFER_APPLETS \
974 || ENABLE_FEATURE_SH_STANDALONE \
975 || ENABLE_FEATURE_SH_NOFORK)
976 if (argv[1][6]) { /* --list-full? */
977 const char *str;
978
979 if (APPLET_IS_NOFORK(i))
980 str = "NOFORK ";
981 else if (APPLET_IS_NOEXEC(i))
982 str = "noexec ";
983# if NUM_SCRIPTS > 0
984 else if (applet_main[i] == scripted_main)
985 str = "script ";
986# endif
987 else
988 str = " ";
989 full_write2_str(str);
990 }
909# endif 991# endif
910 full_write2_str(a); 992 full_write2_str(a);
911 full_write2_str("\n"); 993 full_write2_str("\n");
@@ -917,6 +999,7 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
917 } 999 }
918 1000
919 if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { 1001 if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) {
1002#if !ENABLE_PLATFORM_MINGW32
920 int use_symbolic_links; 1003 int use_symbolic_links;
921 const char *busybox; 1004 const char *busybox;
922 1005
@@ -937,9 +1020,40 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
937 */ 1020 */
938 use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && ++argv); 1021 use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && ++argv);
939 install_links(busybox, use_symbolic_links, argv[2]); 1022 install_links(busybox, use_symbolic_links, argv[2]);
1023#else
1024 /* busybox --install [DIR]
1025 * where DIR is the directory to install to. If DIR is not
1026 * provided put the links in the same directory as busybox.
1027 */
1028 install_links(bb_busybox_exec_path, FALSE, argv[2] ? argv[2] :
1029 dirname(xstrdup(bb_busybox_exec_path)));
1030#endif
940 return 0; 1031 return 0;
941 } 1032 }
942 1033
1034#if ENABLE_PLATFORM_MINGW32 && ENABLE_FEATURE_INSTALLER
1035 if (strcmp(argv[1], "--uninstall") == 0) {
1036 char name[PATH_MAX];
1037 int dry_run = (argv[2] && strcmp(argv[2], "-n") == 0 && ++argv);
1038 const char *file = argv[2];
1039
1040 if (!argv[2])
1041 bb_error_msg_and_die(bb_msg_requires_arg, "--uninstall");
1042
1043 while (enumerate_links(file, name)) {
1044 if (dry_run) {
1045 full_write1_str(name);
1046 full_write1_str("\n");
1047 }
1048 else if (unlink(name) != 0) {
1049 bb_simple_perror_msg(name);
1050 }
1051 file = NULL;
1052 }
1053 return 0;
1054 }
1055#endif
1056
943 if (strcmp(argv[1], "--help") == 0) { 1057 if (strcmp(argv[1], "--help") == 0) {
944 /* "busybox --help [<applet>]" */ 1058 /* "busybox --help [<applet>]" */
945 if (!argv[2]) 1059 if (!argv[2])
@@ -959,15 +1073,42 @@ int busybox_main(int argc UNUSED_PARAM, char **argv)
959# endif 1073# endif
960 1074
961# if NUM_APPLETS > 0 1075# if NUM_APPLETS > 0
1076
1077# if ENABLE_PLATFORM_MINGW32
1078static int interp = 0;
1079char bb_comm[COMM_LEN];
1080char bb_command_line[128];
1081# endif
1082
962void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv) 1083void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv)
963{ 1084{
964 int argc = string_array_len(argv); 1085 int argc = string_array_len(argv);
1086# if ENABLE_PLATFORM_MINGW32
1087 int i;
1088 const char *vmask;
1089 unsigned int mask;
1090# endif
965 1091
966 /* 1092 /*
967 * We do not use argv[0]: do not want to repeat massaging of 1093 * We do not use argv[0]: do not want to repeat massaging of
968 * "-/sbin/halt" -> "halt", for example. 1094 * "-/sbin/halt" -> "halt", for example.
969 */ 1095 */
970 applet_name = name; 1096 applet_name = name;
1097# if ENABLE_PLATFORM_MINGW32
1098 safe_strncpy(bb_comm,
1099 interp ? bb_basename(argv[interp]) : applet_name,
1100 sizeof(bb_comm));
1101
1102 safe_strncpy(bb_command_line, applet_name, sizeof(bb_command_line));
1103 for (i=1; i < argc && argv[i] &&
1104 strlen(bb_command_line) + strlen(argv[i]) + 2 < 128; ++i) {
1105 strcat(strcat(bb_command_line, " "), argv[i]);
1106 }
1107
1108 vmask = getenv("BB_UMASK");
1109 if (vmask && sscanf(vmask, "%o", &mask) == 1)
1110 umask((mode_t)(mask&0777));
1111# endif
971 1112
972 /* Special case. POSIX says "test --help" 1113 /* Special case. POSIX says "test --help"
973 * should be no different from e.g. "test --foo". 1114 * should be no different from e.g. "test --foo".
@@ -993,6 +1134,7 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **ar
993 } 1134 }
994 if (ENABLE_FEATURE_SUID) 1135 if (ENABLE_FEATURE_SUID)
995 check_suid(applet_no); 1136 check_suid(applet_no);
1137
996 xfunc_error_retval = applet_main[applet_no](argc, argv); 1138 xfunc_error_retval = applet_main[applet_no](argc, argv);
997 /* Note: applet_main() may also not return (die on a xfunc or such) */ 1139 /* Note: applet_main() may also not return (die on a xfunc or such) */
998 xfunc_die(); 1140 xfunc_die();
@@ -1075,6 +1217,35 @@ int main(int argc UNUSED_PARAM, char **argv)
1075 argv[0][0] &= 0x7f; 1217 argv[0][0] &= 0x7f;
1076 } 1218 }
1077#endif 1219#endif
1220#if ENABLE_PLATFORM_MINGW32
1221 /* detect if we're running an interpreted script */
1222 if (argv[0][1] == ':' && argv[0][2] == '/') {
1223 switch (argv[0][0]) {
1224 case '2':
1225 ++interp;
1226 /* fall through */
1227 case '1':
1228 ++interp;
1229 argv[0] += 3;
1230 break;
1231 }
1232 }
1233# if ENABLE_FEATURE_EURO
1234 init_codepage();
1235# endif
1236#endif
1237
1238#if defined(__MINGW64_VERSION_MAJOR)
1239 if ( stdin ) {
1240 _setmode(fileno(stdin), _O_BINARY);
1241 }
1242 if ( stdout ) {
1243 _setmode(fileno(stdout), _O_BINARY);
1244 }
1245 if ( stderr ) {
1246 _setmode(fileno(stderr), _O_BINARY);
1247 }
1248#endif
1078 1249
1079#if defined(SINGLE_APPLET_MAIN) 1250#if defined(SINGLE_APPLET_MAIN)
1080 1251
@@ -1107,6 +1278,21 @@ int main(int argc UNUSED_PARAM, char **argv)
1107 applet_name = argv[0]; 1278 applet_name = argv[0];
1108 if (applet_name[0] == '-') 1279 if (applet_name[0] == '-')
1109 applet_name++; 1280 applet_name++;
1281# if ENABLE_PLATFORM_MINGW32
1282 if ( argv[1] && argv[2] && strcmp(argv[1], "--busybox") == 0 ) {
1283 argv += 2;
1284 applet_name = argv[0];
1285 }
1286 else {
1287 char *s;
1288
1289 str_tolower(argv[0]);
1290 bs_to_slash(argv[0]);
1291 if (has_exe_suffix_or_dot(argv[0]) && (s=strrchr(argv[0], '.'))) {
1292 *s = '\0';
1293 }
1294 }
1295# endif
1110 applet_name = bb_basename(applet_name); 1296 applet_name = bb_basename(applet_name);
1111 1297
1112 /* If we are a result of execv("/proc/self/exe"), fix ugly comm of "exe" */ 1298 /* If we are a result of execv("/proc/self/exe"), fix ugly comm of "exe" */
diff --git a/libbb/bb_qsort.c b/libbb/bb_qsort.c
index 505045533..7afddf468 100644
--- a/libbb/bb_qsort.c
+++ b/libbb/bb_qsort.c
@@ -17,3 +17,15 @@ void FAST_FUNC qsort_string_vector(char **sv, unsigned count)
17{ 17{
18 qsort(sv, count, sizeof(char*), bb_pstrcmp); 18 qsort(sv, count, sizeof(char*), bb_pstrcmp);
19} 19}
20
21#if ENABLE_PLATFORM_MINGW32
22static int bb_pstrcasecmp(const void *a, const void *b)
23{
24 return strcasecmp(*(char**)a, *(char**)b);
25}
26
27void FAST_FUNC qsort_string_vector_case(char **sv, unsigned count)
28{
29 qsort(sv, count, sizeof(char*), bb_pstrcasecmp);
30}
31#endif
diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c
index 01a9df0e2..856739c41 100644
--- a/libbb/compare_string_array.c
+++ b/libbb/compare_string_array.c
@@ -27,11 +27,25 @@ char* FAST_FUNC is_prefixed_with(const char *string, const char *key)
27#endif 27#endif
28} 28}
29 29
30#if ENABLE_PLATFORM_MINGW32
31char* FAST_FUNC is_prefixed_with_case(const char *string, const char *key)
32{
33 while (*key != '\0') {
34 if (tolower(*key) != tolower(*string))
35 return NULL;
36 key++;
37 string++;
38 }
39 return (char*)string;
40}
41#endif
42
30/* 43/*
31 * Return NULL if string is not suffixed with key. Return pointer to the 44 * Return NULL if string is not suffixed with key. Return pointer to the
32 * beginning of prefix key in string. If key is an empty string return pointer 45 * beginning of prefix key in string. If key is an empty string return pointer
33 * to the end of string. 46 * to the end of string.
34 */ 47 */
48#if !ENABLE_PLATFORM_MINGW32
35char* FAST_FUNC is_suffixed_with(const char *string, const char *key) 49char* FAST_FUNC is_suffixed_with(const char *string, const char *key)
36{ 50{
37 size_t key_len = strlen(key); 51 size_t key_len = strlen(key);
@@ -46,6 +60,33 @@ char* FAST_FUNC is_suffixed_with(const char *string, const char *key)
46 60
47 return NULL; 61 return NULL;
48} 62}
63#else
64static char* FAST_FUNC is_suffixed(const char *string, const char *key,
65 int (*fn)(const char *, const char*))
66{
67 size_t key_len = strlen(key);
68 ssize_t len_diff = strlen(string) - key_len;
69
70 if (len_diff >= 0) {
71 string += len_diff;
72 if (fn(string, key) == 0) {
73 return (char*)string;
74 }
75 }
76
77 return NULL;
78}
79
80char* FAST_FUNC is_suffixed_with(const char *string, const char *key)
81{
82 return is_suffixed(string, key, strcmp);
83}
84
85char* FAST_FUNC is_suffixed_with_case(const char *string, const char *key)
86{
87 return is_suffixed(string, key, strcasecmp);
88}
89#endif
49 90
50/* returns the array index of the string */ 91/* returns the array index of the string */
51/* (index of first match is returned, or -1) */ 92/* (index of first match is returned, or -1) */
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index 2d6557cd4..1dc515b07 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -105,12 +105,18 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
105 return -1; 105 return -1;
106 } 106 }
107 } else { 107 } else {
108#if ENABLE_PLATFORM_POSIX || ENABLE_FEATURE_EXTRA_FILE_DATA
108 if (source_stat.st_dev == dest_stat.st_dev 109 if (source_stat.st_dev == dest_stat.st_dev
109 && source_stat.st_ino == dest_stat.st_ino 110 && source_stat.st_ino == dest_stat.st_ino
111# if ENABLE_FEATURE_EXTRA_FILE_DATA
112 /* ignore invalid inode numbers */
113 && source_stat.st_ino != 0
114# endif
110 ) { 115 ) {
111 bb_error_msg("'%s' and '%s' are the same file", source, dest); 116 bb_error_msg("'%s' and '%s' are the same file", source, dest);
112 return -1; 117 return -1;
113 } 118 }
119#endif
114 dest_exists = 1; 120 dest_exists = 1;
115 } 121 }
116 122
diff --git a/libbb/executable.c b/libbb/executable.c
index 29d2a2c85..87a40eeda 100644
--- a/libbb/executable.c
+++ b/libbb/executable.c
@@ -39,19 +39,29 @@ char* FAST_FUNC find_executable(const char *filename, char **PATHp)
39 * following the rest of the list. 39 * following the rest of the list.
40 */ 40 */
41 char *p, *n; 41 char *p, *n;
42#if ENABLE_PLATFORM_MINGW32
43 char *w;
44#endif
42 45
43 p = *PATHp; 46 p = *PATHp;
44 while (p) { 47 while (p) {
45 int ex; 48 int ex;
46 49
47 n = strchr(p, ':'); 50 n = strchr(p, PATH_SEP);
48 if (n) *n = '\0'; 51 if (n) *n = '\0';
49 p = concat_path_file( 52 p = concat_path_file(
50 p[0] ? p : ".", /* handle "::" case */ 53 p[0] ? p : ".", /* handle "::" case */
51 filename 54 filename
52 ); 55 );
56 if (n) *n++ = PATH_SEP;
57#if ENABLE_PLATFORM_MINGW32
58 if ((w=alloc_win32_extension(p))) {
59 free(p);
60 p = w;
61 /* following test will succeed */
62 }
63#endif
53 ex = file_is_executable(p); 64 ex = file_is_executable(p);
54 if (n) *n++ = ':';
55 if (ex) { 65 if (ex) {
56 *PATHp = n; 66 *PATHp = n;
57 return p; 67 return p;
diff --git a/libbb/find_mount_point.c b/libbb/find_mount_point.c
index 94bbf1d4a..341c30102 100644
--- a/libbb/find_mount_point.c
+++ b/libbb/find_mount_point.c
@@ -19,14 +19,28 @@
19struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) 19struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too)
20{ 20{
21 struct stat s; 21 struct stat s;
22 FILE *mtab_fp;
23 struct mntent *mountEntry; 22 struct mntent *mountEntry;
23#if !ENABLE_PLATFORM_MINGW32
24 FILE *mtab_fp;
24 dev_t devno_of_name; 25 dev_t devno_of_name;
25 bool block_dev; 26 bool block_dev;
27#else
28 static char mnt_fsname[4];
29 static char mnt_dir[4];
30 static char mnt_type[1];
31 static char mnt_opts[1];
32 static struct mntent my_mount_entry = {
33 mnt_fsname, mnt_dir, mnt_type, mnt_opts, 0, 0
34 };
35 char *current;
36 const char *path;
37 DWORD len;
38#endif
26 39
27 if (stat(name, &s) != 0) 40 if (stat(name, &s) != 0)
28 return NULL; 41 return NULL;
29 42
43#if !ENABLE_PLATFORM_MINGW32
30 devno_of_name = s.st_dev; 44 devno_of_name = s.st_dev;
31 block_dev = 0; 45 block_dev = 0;
32 /* Why S_ISCHR? - UBI volumes use char devices, not block */ 46 /* Why S_ISCHR? - UBI volumes use char devices, not block */
@@ -63,6 +77,35 @@ struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too)
63 break; 77 break;
64 } 78 }
65 endmntent(mtab_fp); 79 endmntent(mtab_fp);
80#else
81 mountEntry = NULL;
82 path = NULL;
83 current = NULL;
84
85 if ( isalpha(name[0]) && name[1] == ':' ) {
86 path = name;
87 }
88 else {
89 if ( (len=GetCurrentDirectory(0, NULL)) > 0 &&
90 (current=malloc(len+1)) != NULL &&
91 GetCurrentDirectory(len, current) ) {
92 path = current;
93 }
94 }
95
96 if ( path && isalpha(path[0]) && path[1] == ':' ) {
97 mnt_fsname[0] = path[0];
98 mnt_fsname[1] = path[1];
99 mnt_fsname[2] = '\0';
100 mnt_dir[0] = path[0];
101 mnt_dir[1] = path[1];
102 mnt_dir[2] = '\\';
103 mnt_dir[3] = '\0';
104
105 mountEntry = &my_mount_entry;
106 }
107 free(current);
108#endif
66 109
67 return mountEntry; 110 return mountEntry;
68} 111}
diff --git a/libbb/find_pid_by_name.c b/libbb/find_pid_by_name.c
index abbf293e8..52debb171 100644
--- a/libbb/find_pid_by_name.c
+++ b/libbb/find_pid_by_name.c
@@ -39,8 +39,10 @@ and therefore comm field contains "exe".
39 39
40static int comm_match(procps_status_t *p, const char *procName) 40static int comm_match(procps_status_t *p, const char *procName)
41{ 41{
42#if !ENABLE_PLATFORM_MINGW32
42 int argv1idx; 43 int argv1idx;
43 const char *argv1; 44 const char *argv1;
45#endif
44 46
45 if (strncmp(p->comm, procName, 15) != 0) 47 if (strncmp(p->comm, procName, 15) != 0)
46 return 0; /* comm does not match */ 48 return 0; /* comm does not match */
@@ -55,6 +57,7 @@ static int comm_match(procps_status_t *p, const char *procName)
55 * This can be crazily_long_script_name.sh! 57 * This can be crazily_long_script_name.sh!
56 * The telltale sign is basename(argv[1]) == procName */ 58 * The telltale sign is basename(argv[1]) == procName */
57 59
60#if !ENABLE_PLATFORM_MINGW32
58 if (!p->argv0) 61 if (!p->argv0)
59 return 0; 62 return 0;
60 63
@@ -65,6 +68,7 @@ static int comm_match(procps_status_t *p, const char *procName)
65 68
66 if (strcmp(bb_basename(argv1), procName) != 0) 69 if (strcmp(bb_basename(argv1), procName) != 0)
67 return 0; 70 return 0;
71#endif
68 72
69 return 1; 73 return 1;
70} 74}
@@ -87,10 +91,12 @@ pid_t* FAST_FUNC find_pid_by_name(const char *procName)
87 pidList = xzalloc(sizeof(*pidList)); 91 pidList = xzalloc(sizeof(*pidList));
88 while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN|PSSCAN_EXE))) { 92 while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_COMM|PSSCAN_ARGVN|PSSCAN_EXE))) {
89 if (comm_match(p, procName) 93 if (comm_match(p, procName)
94#if !ENABLE_PLATFORM_MINGW32
90 /* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/ 95 /* or we require argv0 to match (essential for matching reexeced /proc/self/exe)*/
91 || (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0) 96 || (p->argv0 && strcmp(bb_basename(p->argv0), procName) == 0)
92 /* or we require /proc/PID/exe link to match */ 97 /* or we require /proc/PID/exe link to match */
93 || (p->exe && strcmp(bb_basename(p->exe), procName) == 0) 98 || (p->exe && strcmp(bb_basename(p->exe), procName) == 0)
99#endif
94 ) { 100 ) {
95 pidList = xrealloc_vector(pidList, 2, i); 101 pidList = xrealloc_vector(pidList, 2, i);
96 pidList[i++] = p->pid; 102 pidList[i++] = p->pid;
diff --git a/libbb/get_last_path_component.c b/libbb/get_last_path_component.c
index 04fdf2a3e..3a9b9237e 100644
--- a/libbb/get_last_path_component.c
+++ b/libbb/get_last_path_component.c
@@ -10,9 +10,16 @@
10 10
11const char* FAST_FUNC bb_basename(const char *name) 11const char* FAST_FUNC bb_basename(const char *name)
12{ 12{
13#if ENABLE_PLATFORM_MINGW32
14 const char *cp;
15 for (cp = name; *cp; cp++)
16 if (*cp == '/' || *cp == '\\')
17 name = cp + 1;
18#else
13 const char *cp = strrchr(name, '/'); 19 const char *cp = strrchr(name, '/');
14 if (cp) 20 if (cp)
15 return cp + 1; 21 return cp + 1;
22#endif
16 return name; 23 return name;
17} 24}
18 25
@@ -26,8 +33,18 @@ char* FAST_FUNC bb_get_last_path_component_nostrip(const char *path)
26{ 33{
27 char *slash = strrchr(path, '/'); 34 char *slash = strrchr(path, '/');
28 35
36#if ENABLE_PLATFORM_MINGW32
37 const char *start = has_dos_drive_prefix(path) ? path+2 : path;
38
39 if (!slash)
40 slash = strrchr(path, '\\');
41
42 if (!slash || (slash == start && !slash[1]))
43 return (char*)path;
44#else
29 if (!slash || (slash == path && !slash[1])) 45 if (!slash || (slash == path && !slash[1]))
30 return (char*)path; 46 return (char*)path;
47#endif
31 48
32 return slash + 1; 49 return slash + 1;
33} 50}
@@ -42,9 +59,20 @@ char* FAST_FUNC bb_get_last_path_component_strip(char *path)
42{ 59{
43 char *slash = last_char_is(path, '/'); 60 char *slash = last_char_is(path, '/');
44 61
62#if ENABLE_PLATFORM_MINGW32
63 const char *start = has_dos_drive_prefix(path) ? path+2 : path;
64
65 if (!slash)
66 slash = last_char_is(path, '\\');
67
68 if (slash)
69 while ((*slash == '/' || *slash == '\\') && slash != start)
70 *slash-- = '\0';
71#else
45 if (slash) 72 if (slash)
46 while (*slash == '/' && slash != path) 73 while (*slash == '/' && slash != path)
47 *slash-- = '\0'; 74 *slash-- = '\0';
75#endif
48 76
49 return bb_get_last_path_component_nostrip(path); 77 return bb_get_last_path_component_nostrip(path);
50} 78}
diff --git a/libbb/get_line_from_file.c b/libbb/get_line_from_file.c
index 903ff1fb6..929bab78a 100644
--- a/libbb/get_line_from_file.c
+++ b/libbb/get_line_from_file.c
@@ -59,6 +59,10 @@ char* FAST_FUNC xmalloc_fgetline(FILE *file)
59 59
60 if (i && c[--i] == '\n') 60 if (i && c[--i] == '\n')
61 c[i] = '\0'; 61 c[i] = '\0';
62#if ENABLE_PLATFORM_MINGW32
63 if (i && c[--i] == '\r')
64 c[i] = '\0';
65#endif
62 66
63 return c; 67 return c;
64} 68}
diff --git a/libbb/human_readable.c b/libbb/human_readable.c
index 09221a186..3199ede6e 100644
--- a/libbb/human_readable.c
+++ b/libbb/human_readable.c
@@ -38,7 +38,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val,
38 if (val == 0) 38 if (val == 0)
39 return "0"; 39 return "0";
40 40
41 fmt = "%llu"; 41 fmt = "%"LL_FMT"u";
42 if (block_size > 1) 42 if (block_size > 1)
43 val *= block_size; 43 val *= block_size;
44 frac = 0; 44 frac = 0;
@@ -52,7 +52,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val,
52 while ((val >= 1024) 52 while ((val >= 1024)
53 /* && (u < unit_chars + sizeof(unit_chars) - 1) - always true */ 53 /* && (u < unit_chars + sizeof(unit_chars) - 1) - always true */
54 ) { 54 ) {
55 fmt = "%llu.%u%c"; 55 fmt = "%"LL_FMT"u.%u%c";
56 u++; 56 u++;
57 frac = (((unsigned)val % 1024) * 10 + 1024/2) / 1024; 57 frac = (((unsigned)val % 1024) * 10 + 1024/2) / 1024;
58 val /= 1024; 58 val /= 1024;
@@ -67,7 +67,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val,
67 if (frac >= 5) { 67 if (frac >= 5) {
68 ++val; 68 ++val;
69 } 69 }
70 fmt = "%llu%*c"; 70 fmt = "%"LL_FMT"u%*c";
71 frac = 1; 71 frac = 1;
72 } 72 }
73#endif 73#endif
diff --git a/libbb/inode_hash.c b/libbb/inode_hash.c
index a125244ca..f2cc417bc 100644
--- a/libbb/inode_hash.c
+++ b/libbb/inode_hash.c
@@ -61,6 +61,11 @@ void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *
61 int i; 61 int i;
62 ino_dev_hashtable_bucket_t *bucket; 62 ino_dev_hashtable_bucket_t *bucket;
63 63
64#if ENABLE_FEATURE_EXTRA_FILE_DATA
65 /* ignore invalid inode numbers */
66 if (statbuf->st_ino == 0)
67 return;
68#endif
64 if (!name) 69 if (!name)
65 name = ""; 70 name = "";
66 bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name)); 71 bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name));
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 1d5fef5ee..3725dba0d 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -356,7 +356,7 @@ int adjust_width_and_validate_wc(unsigned *width_adj, int wc);
356/* Put 'command_ps[cursor]', cursor++. 356/* Put 'command_ps[cursor]', cursor++.
357 * Advance cursor on screen. If we reached right margin, scroll text up 357 * Advance cursor on screen. If we reached right margin, scroll text up
358 * and remove terminal margin effect by printing 'next_char' */ 358 * and remove terminal margin effect by printing 'next_char' */
359#define HACK_FOR_WRONG_WIDTH 1 359#define HACK_FOR_WRONG_WIDTH 1 && !ENABLE_PLATFORM_MINGW32
360static void put_cur_glyph_and_inc_cursor(void) 360static void put_cur_glyph_and_inc_cursor(void)
361{ 361{
362 CHAR_T c = command_ps[cursor]; 362 CHAR_T c = command_ps[cursor];
@@ -419,6 +419,42 @@ static void put_cur_glyph_and_inc_cursor(void)
419 } 419 }
420} 420}
421 421
422#if ENABLE_PLATFORM_MINGW32
423static void inc_cursor(void)
424{
425 CHAR_T c = command_ps[cursor];
426 unsigned width = 0;
427 int ofs_to_right;
428
429 /* advance cursor */
430 cursor++;
431 if (unicode_status == UNICODE_ON) {
432 IF_UNICODE_WIDE_WCHARS(width = cmdedit_x;)
433 c = adjust_width_and_validate_wc(&cmdedit_x, c);
434 IF_UNICODE_WIDE_WCHARS(width = cmdedit_x - width;)
435 } else {
436 cmdedit_x++;
437 }
438
439 ofs_to_right = cmdedit_x - cmdedit_termw;
440 if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right <= 0) {
441 /* cursor remains on this line */
442 printf(ESC"[1C");
443 }
444
445 if (ofs_to_right >= 0) {
446 /* we go to the next line */
447 printf(ESC"[1B");
448 bb_putchar('\r');
449 cmdedit_y++;
450 if (!ENABLE_UNICODE_WIDE_WCHARS || ofs_to_right == 0) {
451 width = 0;
452 }
453 cmdedit_x = width;
454 }
455}
456#endif
457
422/* Move to end of line (by printing all chars till the end) */ 458/* Move to end of line (by printing all chars till the end) */
423static void put_till_end_and_adv_cursor(void) 459static void put_till_end_and_adv_cursor(void)
424{ 460{
@@ -478,6 +514,7 @@ static void input_backward(unsigned num)
478 514
479 if (cmdedit_x >= num) { 515 if (cmdedit_x >= num) {
480 cmdedit_x -= num; 516 cmdedit_x -= num;
517#if !ENABLE_PLATFORM_MINGW32
481 if (num <= 4) { 518 if (num <= 4) {
482 /* This is longer by 5 bytes on x86. 519 /* This is longer by 5 bytes on x86.
483 * Also gets miscompiled for ARM users 520 * Also gets miscompiled for ARM users
@@ -490,6 +527,7 @@ static void input_backward(unsigned num)
490 } while (--num); 527 } while (--num);
491 return; 528 return;
492 } 529 }
530#endif
493 printf(ESC"[%uD", num); 531 printf(ESC"[%uD", num);
494 return; 532 return;
495 } 533 }
@@ -628,7 +666,11 @@ static void input_backspace(void)
628static void input_forward(void) 666static void input_forward(void)
629{ 667{
630 if (cursor < command_len) 668 if (cursor < command_len)
669#if !ENABLE_PLATFORM_MINGW32
631 put_cur_glyph_and_inc_cursor(); 670 put_cur_glyph_and_inc_cursor();
671#else
672 inc_cursor();
673#endif
632} 674}
633 675
634#if ENABLE_FEATURE_TAB_COMPLETION 676#if ENABLE_FEATURE_TAB_COMPLETION
@@ -639,6 +681,14 @@ static void input_forward(void)
639//Also, perhaps "foo b<TAB> needs to complete to "foo bar" <cursor>, 681//Also, perhaps "foo b<TAB> needs to complete to "foo bar" <cursor>,
640//not "foo bar <cursor>... 682//not "foo bar <cursor>...
641 683
684# if ENABLE_PLATFORM_MINGW32
685/* use case-insensitive comparisons for filenames */
686# define is_prefixed_with(s, k) is_prefixed_with_case(s, k)
687# define qsort_string_vector(s, c) qsort_string_vector_case(s, c)
688# define strcmp(s, t) strcasecmp(s, t)
689# define strncmp(s, t, n) strncasecmp(s, t, n)
690# endif
691
642static void free_tab_completion_data(void) 692static void free_tab_completion_data(void)
643{ 693{
644 if (matches) { 694 if (matches) {
@@ -655,8 +705,12 @@ static void add_match(char *matched)
655 while (*p) { 705 while (*p) {
656 /* ESC attack fix: drop any string with control chars */ 706 /* ESC attack fix: drop any string with control chars */
657 if (*p < ' ' 707 if (*p < ' '
708# if !ENABLE_PLATFORM_MINGW32
658 || (!ENABLE_UNICODE_SUPPORT && *p >= 0x7f) 709 || (!ENABLE_UNICODE_SUPPORT && *p >= 0x7f)
659 || (ENABLE_UNICODE_SUPPORT && *p == 0x7f) 710 || (ENABLE_UNICODE_SUPPORT && *p == 0x7f)
711# else
712 || *p == 0x7f
713# endif
660 ) { 714 ) {
661 free(matched); 715 free(matched);
662 return; 716 return;
@@ -748,7 +802,7 @@ static int path_parse(char ***p)
748 tmp = (char*)pth; 802 tmp = (char*)pth;
749 npth = 1; /* path component count */ 803 npth = 1; /* path component count */
750 while (1) { 804 while (1) {
751 tmp = strchr(tmp, ':'); 805 tmp = strchr(tmp, PATH_SEP);
752 if (!tmp) 806 if (!tmp)
753 break; 807 break;
754 tmp++; 808 tmp++;
@@ -761,7 +815,7 @@ static int path_parse(char ***p)
761 res[0] = tmp = xstrdup(pth); 815 res[0] = tmp = xstrdup(pth);
762 npth = 1; 816 npth = 1;
763 while (1) { 817 while (1) {
764 tmp = strchr(tmp, ':'); 818 tmp = strchr(tmp, PATH_SEP);
765 if (!tmp) 819 if (!tmp)
766 break; 820 break;
767 *tmp++ = '\0'; /* ':' -> '\0' */ 821 *tmp++ = '\0'; /* ':' -> '\0' */
@@ -847,6 +901,12 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type)
847 if (stat(found, &st) && lstat(found, &st)) 901 if (stat(found, &st) && lstat(found, &st))
848 goto cont; /* hmm, remove in progress? */ 902 goto cont; /* hmm, remove in progress? */
849 903
904# if ENABLE_PLATFORM_MINGW32
905 if (type == FIND_EXE_ONLY && !S_ISDIR(st.st_mode) &&
906 !file_is_executable(found))
907 goto cont;
908# endif
909
850 /* Save only name */ 910 /* Save only name */
851 len = strlen(name_found); 911 len = strlen(name_found);
852 found = xrealloc(found, len + 2); /* +2: for slash and NUL */ 912 found = xrealloc(found, len + 2); /* +2: for slash and NUL */
@@ -1217,7 +1277,11 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1217 for (cp = chosen_match; *cp; cp++) { 1277 for (cp = chosen_match; *cp; cp++) {
1218 unsigned n; 1278 unsigned n;
1219 for (n = 1; n < num_matches; n++) { 1279 for (n = 1; n < num_matches; n++) {
1280# if !ENABLE_PLATFORM_MINGW32
1220 if (matches[n][cp - chosen_match] != *cp) { 1281 if (matches[n][cp - chosen_match] != *cp) {
1282# else
1283 if (tolower(matches[n][cp - chosen_match]) != tolower(*cp)) {
1284# endif
1221 goto stop; 1285 goto stop;
1222 } 1286 }
1223 } 1287 }
@@ -1253,7 +1317,11 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1253 /* save tail */ 1317 /* save tail */
1254 strcpy(match_buf, &command_ps[cursor]); 1318 strcpy(match_buf, &command_ps[cursor]);
1255 /* add match and tail */ 1319 /* add match and tail */
1320#if ENABLE_PLATFORM_MINGW32
1321 sprintf(&command_ps[cursor-match_pfx_len], "%s%s", chosen_match, match_buf);
1322#else
1256 sprintf(&command_ps[cursor], "%s%s", chosen_match + match_pfx_len, match_buf); 1323 sprintf(&command_ps[cursor], "%s%s", chosen_match + match_pfx_len, match_buf);
1324#endif
1257 command_len = strlen(command_ps); 1325 command_len = strlen(command_ps);
1258 /* new pos */ 1326 /* new pos */
1259 pos = cursor + len_found - match_pfx_len; 1327 pos = cursor + len_found - match_pfx_len;
@@ -1290,6 +1358,13 @@ static NOINLINE void input_tab(smallint *lastWasTab)
1290 free(match_buf); 1358 free(match_buf);
1291} 1359}
1292 1360
1361# if ENABLE_PLATFORM_MINGW32
1362# undef is_prefixed_with
1363# undef qsort_string_vector
1364# undef strcmp
1365# undef strncmp
1366# endif
1367
1293#endif /* FEATURE_TAB_COMPLETION */ 1368#endif /* FEATURE_TAB_COMPLETION */
1294 1369
1295 1370
@@ -2332,7 +2407,7 @@ static void sigaction2(int sig, struct sigaction *act)
2332 */ 2407 */
2333int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize) 2408int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize)
2334{ 2409{
2335 int len, n; 2410 int len IF_NOT_PLATFORM_MINGW32(, n);
2336 int timeout; 2411 int timeout;
2337#if ENABLE_FEATURE_TAB_COMPLETION 2412#if ENABLE_FEATURE_TAB_COMPLETION
2338 smallint lastWasTab = 0; 2413 smallint lastWasTab = 0;
@@ -2342,15 +2417,23 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2342 smallint vi_cmdmode = 0; 2417 smallint vi_cmdmode = 0;
2343#endif 2418#endif
2344 struct termios initial_settings; 2419 struct termios initial_settings;
2420#if !ENABLE_PLATFORM_MINGW32
2345 struct termios new_settings; 2421 struct termios new_settings;
2422#endif
2346 char read_key_buffer[KEYCODE_BUFFER_SIZE]; 2423 char read_key_buffer[KEYCODE_BUFFER_SIZE];
2347 2424
2348 INIT_S(); 2425 INIT_S();
2349 2426
2427#if !ENABLE_PLATFORM_MINGW32
2350 n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0 2428 n = get_termios_and_make_raw(STDIN_FILENO, &new_settings, &initial_settings, 0
2351 | TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */ 2429 | TERMIOS_CLEAR_ISIG /* turn off INTR (ctrl-C), QUIT, SUSP */
2352 ); 2430 );
2353 if (n != 0 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON) { 2431 if (n != 0 || (initial_settings.c_lflag & (ECHO|ICANON)) == ICANON) {
2432#else
2433 initial_settings.c_cc[VINTR] = CTRL('C');
2434 initial_settings.c_cc[VEOF] = CTRL('D');
2435 if (!isatty(0) || !isatty(1)) {
2436#endif
2354 /* Happens when e.g. stty -echo was run before. 2437 /* Happens when e.g. stty -echo was run before.
2355 * But if ICANON is not set, we don't come here. 2438 * But if ICANON is not set, we don't come here.
2356 * (example: interactive python ^Z-backgrounded, 2439 * (example: interactive python ^Z-backgrounded,
@@ -2404,7 +2487,9 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2404#endif 2487#endif
2405#define command command_must_not_be_used 2488#define command command_must_not_be_used
2406 2489
2490#if !ENABLE_PLATFORM_MINGW32
2407 tcsetattr_stdin_TCSANOW(&new_settings); 2491 tcsetattr_stdin_TCSANOW(&new_settings);
2492#endif
2408 2493
2409#if ENABLE_USERNAME_OR_HOMEDIR 2494#if ENABLE_USERNAME_OR_HOMEDIR
2410 { 2495 {
@@ -2457,6 +2542,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2457 } 2542 }
2458#endif 2543#endif
2459 ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); 2544 ic = ic_raw = lineedit_read_key(read_key_buffer, timeout);
2545#if ENABLE_PLATFORM_MINGW32
2546 /* scroll to cursor position on any keypress */
2547 if (isatty(fileno(stdin)) && isatty(fileno(stdout)))
2548 move_cursor_row(0);
2549#endif
2460 2550
2461#if ENABLE_FEATURE_REVERSE_SEARCH 2551#if ENABLE_FEATURE_REVERSE_SEARCH
2462 again: 2552 again:
@@ -2518,6 +2608,13 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2518 input_tab(&lastWasTab); 2608 input_tab(&lastWasTab);
2519 break; 2609 break;
2520#endif 2610#endif
2611#if ENABLE_PLATFORM_MINGW32
2612 case CTRL('Z'):
2613 command_ps[command_len] = '\0';
2614 bs_to_slash(command_ps);
2615 redraw(cmdedit_y, 0);
2616 break;
2617#endif
2521 case CTRL('K'): 2618 case CTRL('K'):
2522 /* Control-k -- clear to end of line */ 2619 /* Control-k -- clear to end of line */
2523 command_ps[cursor] = BB_NUL; 2620 command_ps[cursor] = BB_NUL;
@@ -2890,8 +2987,10 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2890 free_tab_completion_data(); 2987 free_tab_completion_data();
2891#endif 2988#endif
2892 2989
2990#if !ENABLE_PLATFORM_MINGW32
2893 /* restore initial_settings */ 2991 /* restore initial_settings */
2894 tcsetattr_stdin_TCSANOW(&initial_settings); 2992 tcsetattr_stdin_TCSANOW(&initial_settings);
2993#endif
2895#if ENABLE_FEATURE_EDITING_WINCH 2994#if ENABLE_FEATURE_EDITING_WINCH
2896 /* restore SIGWINCH handler */ 2995 /* restore SIGWINCH handler */
2897 sigaction_set(SIGWINCH, &S.SIGWINCH_handler); 2996 sigaction_set(SIGWINCH, &S.SIGWINCH_handler);
diff --git a/libbb/make_directory.c b/libbb/make_directory.c
index 9b03bb8d0..9af5552d5 100644
--- a/libbb/make_directory.c
+++ b/libbb/make_directory.c
@@ -49,11 +49,40 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
49 } 49 }
50 50
51 org_mask = cur_mask = (mode_t)-1L; 51 org_mask = cur_mask = (mode_t)-1L;
52#if ENABLE_PLATFORM_MINGW32
53 /* normalise path separators, path is already assumed writable */
54 bs_to_slash(path);
55#endif
52 s = path; 56 s = path;
53 while (1) { 57 while (1) {
54 c = '\0'; 58 c = '\0';
55 59
56 if (flags & FILEUTILS_RECUR) { /* Get the parent */ 60 if (flags & FILEUTILS_RECUR) { /* Get the parent */
61#if ENABLE_PLATFORM_MINGW32
62 if (s == path && *s && s[1] == ':') {
63 /* skip drive letter */
64 s += 2;
65 }
66 else if (s == path && s[0] == '/' && s[1] == '/' ) {
67 /* skip UNC server and share */
68 int count = 0;
69 s += 2;
70 while (*s) {
71 if (*s == '/') {
72 do {
73 ++s;
74 } while (*s == '/');
75 if (++count == 2) {
76 --s;
77 break;
78 }
79 }
80 else {
81 ++s;
82 }
83 }
84 }
85#endif
57 /* Bypass leading non-'/'s and then subsequent '/'s */ 86 /* Bypass leading non-'/'s and then subsequent '/'s */
58 while (*s) { 87 while (*s) {
59 if (*s == '/') { 88 if (*s == '/') {
diff --git a/libbb/messages.c b/libbb/messages.c
index 6914d5701..f5bbd3e32 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -27,7 +27,9 @@ const char bb_msg_standard_output[] ALIGN1 = "standard output";
27 27
28const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF"; 28const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF";
29 29
30#if !ENABLE_PLATFORM_MINGW32
30const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; 31const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH;
32#endif
31const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; 33const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL;
32/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, 34/* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
33 * but I want to save a few bytes here. Check libbb.h before changing! */ 35 * but I want to save a few bytes here. Check libbb.h before changing! */
diff --git a/libbb/mode_string.c b/libbb/mode_string.c
index 5ffd5683e..6c5c08acd 100644
--- a/libbb/mode_string.c
+++ b/libbb/mode_string.c
@@ -17,7 +17,7 @@
17#endif 17#endif
18 18
19#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \ 19#if ( S_IFSOCK!= 0140000 ) || ( S_IFLNK != 0120000 ) \
20 || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 ) \ 20 || ( S_IFREG != 0100000 ) || ( S_IFBLK != 0060000 && S_IFBLK != 0030000 ) \
21 || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \ 21 || ( S_IFDIR != 0040000 ) || ( S_IFCHR != 0020000 ) \
22 || ( S_IFIFO != 0010000 ) 22 || ( S_IFIFO != 0010000 )
23#warning mode type bitflag value assumption(s) violated! falling back to larger version 23#warning mode type bitflag value assumption(s) violated! falling back to larger version
diff --git a/libbb/printable_string.c b/libbb/printable_string.c
index a814fd03c..2e8895a4f 100644
--- a/libbb/printable_string.c
+++ b/libbb/printable_string.c
@@ -42,7 +42,7 @@ const char* FAST_FUNC printable_string2(uni_stat_t *stats, const char *str)
42 unsigned char c = *d; 42 unsigned char c = *d;
43 if (c == '\0') 43 if (c == '\0')
44 break; 44 break;
45 if (c < ' ' || c >= 0x7f) 45 if (c < ' ' || (c >= 0x7f && !ENABLE_PLATFORM_MINGW32))
46 *d = '?'; 46 *d = '?';
47 d++; 47 d++;
48 } 48 }
diff --git a/libbb/procps.c b/libbb/procps.c
index af3ad86ff..e6892d7ff 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -74,6 +74,7 @@ const char* FAST_FUNC get_cached_groupname(gid_t gid)
74 return get_cached(&groupname, gid, gid2group_utoa); 74 return get_cached(&groupname, gid, gid2group_utoa);
75} 75}
76 76
77#if !ENABLE_PLATFORM_MINGW32
77 78
78#define PROCPS_BUFSIZE 1024 79#define PROCPS_BUFSIZE 1024
79 80
@@ -621,6 +622,8 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm)
621 } 622 }
622} 623}
623 624
625#endif /* ENABLE_PLATFORM_MINGW32 */
626
624/* from kernel: 627/* from kernel:
625 // pid comm S ppid pgid sid tty_nr tty_pgrp flg 628 // pid comm S ppid pgid sid tty_nr tty_pgrp flg
626 sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ 629 sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
diff --git a/libbb/read_printf.c b/libbb/read_printf.c
index b6a17cc36..e47ac7afe 100644
--- a/libbb/read_printf.c
+++ b/libbb/read_printf.c
@@ -93,6 +93,11 @@ char* FAST_FUNC xmalloc_reads(int fd, size_t *maxsz_p)
93 break; 93 break;
94 p++; 94 p++;
95 } 95 }
96#if ENABLE_PLATFORM_MINGW32
97 if ( p != buf && *(p-1) == '\r' ) {
98 --p;
99 }
100#endif
96 *p = '\0'; 101 *p = '\0';
97 if (maxsz_p) 102 if (maxsz_p)
98 *maxsz_p = p - buf; 103 *maxsz_p = p - buf;
diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c
index f7d598c7a..036ad0038 100644
--- a/libbb/u_signal_names.c
+++ b/libbb/u_signal_names.c
@@ -27,6 +27,10 @@
27 27
28#include "libbb.h" 28#include "libbb.h"
29 29
30#if ENABLE_PLATFORM_MINGW32
31# undef SIGPIPE
32#endif
33
30/* Believe it or not, but some arches have more than 32 SIGs! 34/* Believe it or not, but some arches have more than 32 SIGs!
31 * HPPA: SIGSTKFLT == 36. */ 35 * HPPA: SIGSTKFLT == 36. */
32 36
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 1aac27b36..2d497d754 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -150,6 +150,7 @@ void FAST_FUNC run_noexec_applet_and_exit(int a, const char *name, char **argv)
150 * Higher-level code, hiding optional NOFORK/NOEXEC trickery. 150 * Higher-level code, hiding optional NOFORK/NOEXEC trickery.
151 */ 151 */
152 152
153#if !ENABLE_PLATFORM_MINGW32
153/* This does a fork/exec in one call, using vfork(). Returns PID of new child, 154/* This does a fork/exec in one call, using vfork(). Returns PID of new child,
154 * -1 for failure. Runs argv[0], searching path if that has no / in it. */ 155 * -1 for failure. Runs argv[0], searching path if that has no / in it. */
155pid_t FAST_FUNC spawn(char **argv) 156pid_t FAST_FUNC spawn(char **argv)
@@ -191,6 +192,7 @@ pid_t FAST_FUNC spawn(char **argv)
191 } 192 }
192 return pid; 193 return pid;
193} 194}
195#endif
194 196
195/* Die with an error message if we can't spawn a child process. */ 197/* Die with an error message if we can't spawn a child process. */
196pid_t FAST_FUNC xspawn(char **argv) 198pid_t FAST_FUNC xspawn(char **argv)
@@ -211,6 +213,7 @@ int FAST_FUNC spawn_and_wait(char **argv)
211 if (APPLET_IS_NOFORK(a)) 213 if (APPLET_IS_NOFORK(a))
212 return run_nofork_applet(a, argv); 214 return run_nofork_applet(a, argv);
213# if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */ 215# if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */
216# if !ENABLE_PLATFORM_MINGW32 /* and then only if not on Microsoft Windows */
214 if (APPLET_IS_NOEXEC(a)) { 217 if (APPLET_IS_NOEXEC(a)) {
215 fflush_all(); 218 fflush_all();
216 rc = fork(); 219 rc = fork();
@@ -220,6 +223,7 @@ int FAST_FUNC spawn_and_wait(char **argv)
220 /* child */ 223 /* child */
221 run_noexec_applet_and_exit(a, argv[0], argv); 224 run_noexec_applet_and_exit(a, argv[0], argv);
222 } 225 }
226# endif
223# endif 227# endif
224 } 228 }
225#endif 229#endif
@@ -227,6 +231,7 @@ int FAST_FUNC spawn_and_wait(char **argv)
227 return wait4pid(rc); 231 return wait4pid(rc);
228} 232}
229 233
234#if !ENABLE_PLATFORM_MINGW32
230#if !BB_MMU 235#if !BB_MMU
231void FAST_FUNC re_exec(char **argv) 236void FAST_FUNC re_exec(char **argv)
232{ 237{
@@ -313,3 +318,4 @@ void FAST_FUNC bb_sanitize_stdio(void)
313{ 318{
314 bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE, NULL); 319 bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE, NULL);
315} 320}
321#endif /* !MINGW32 */
diff --git a/libbb/xatonum_template.c b/libbb/xatonum_template.c
index e0471983c..0d5d35b47 100644
--- a/libbb/xatonum_template.c
+++ b/libbb/xatonum_template.c
@@ -67,7 +67,7 @@ unsigned type FAST_FUNC xstrtou(_range_sfx)(const char *numstr, int base,
67 if (r >= lower && r <= upper) 67 if (r >= lower && r <= upper)
68 return r; 68 return r;
69 range: 69 range:
70 bb_error_msg_and_die("number %s is not in %llu..%llu range", 70 bb_error_msg_and_die("number %s is not in %"LL_FMT"u..%"LL_FMT"u range",
71 numstr, (unsigned long long)lower, 71 numstr, (unsigned long long)lower,
72 (unsigned long long)upper); 72 (unsigned long long)upper);
73 inval: 73 inval:
@@ -144,7 +144,8 @@ type FAST_FUNC xstrto(_range_sfx)(const char *numstr, int base,
144 } 144 }
145 145
146 if (r < lower || r > upper) { 146 if (r < lower || r > upper) {
147 bb_error_msg_and_die("number %s is not in %lld..%lld range", 147 bb_error_msg_and_die("number %s is not in "
148 "%"LL_FMT"d..%"LL_FMT"d range",
148 numstr, (long long)lower, (long long)upper); 149 numstr, (long long)lower, (long long)upper);
149 } 150 }
150 151
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index 39e56b223..a6127508b 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -68,6 +68,7 @@ int FAST_FUNC setsockopt_bindtodevice(int fd UNUSED_PARAM,
68} 68}
69#endif 69#endif
70 70
71#if !ENABLE_PLATFORM_MINGW32
71static len_and_sockaddr* get_lsa(int fd, int (*get_name)(int fd, struct sockaddr *addr, socklen_t *addrlen)) 72static len_and_sockaddr* get_lsa(int fd, int (*get_name)(int fd, struct sockaddr *addr, socklen_t *addrlen))
72{ 73{
73 len_and_sockaddr lsa; 74 len_and_sockaddr lsa;
@@ -96,16 +97,17 @@ len_and_sockaddr* FAST_FUNC get_peer_lsa(int fd)
96{ 97{
97 return get_lsa(fd, getpeername); 98 return get_lsa(fd, getpeername);
98} 99}
100#endif
99 101
100void FAST_FUNC xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) 102void FAST_FUNC xconnect(int s, const struct sockaddr *saddr, socklen_t addrlen)
101{ 103{
102 if (connect(s, s_addr, addrlen) < 0) { 104 if (connect(s, saddr, addrlen) < 0) {
103 if (ENABLE_FEATURE_CLEAN_UP) 105 if (ENABLE_FEATURE_CLEAN_UP)
104 close(s); 106 close(s);
105 if (s_addr->sa_family == AF_INET) 107 if (saddr->sa_family == AF_INET)
106 bb_perror_msg_and_die("%s (%s)", 108 bb_perror_msg_and_die("%s (%s)",
107 "can't connect to remote host", 109 "can't connect to remote host",
108 inet_ntoa(((struct sockaddr_in *)s_addr)->sin_addr)); 110 inet_ntoa(((struct sockaddr_in *)saddr)->sin_addr));
109 bb_perror_msg_and_die("can't connect to remote host"); 111 bb_perror_msg_and_die("can't connect to remote host");
110 } 112 }
111} 113}
@@ -352,6 +354,10 @@ int FAST_FUNC xsocket_type(len_and_sockaddr **lsap, int family, int sock_type)
352#if ENABLE_FEATURE_IPV6 354#if ENABLE_FEATURE_IPV6
353 fd = socket(AF_INET6, sock_type, 0); 355 fd = socket(AF_INET6, sock_type, 0);
354 if (fd >= 0) { 356 if (fd >= 0) {
357#if ENABLE_PLATFORM_MINGW32
358 DWORD buffer = 0;
359 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &buffer, sizeof(DWORD));
360#endif
355 family = AF_INET6; 361 family = AF_INET6;
356 goto done; 362 goto done;
357 } 363 }
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index b4d512bd6..57bda6204 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -268,6 +268,7 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh
268 int err; 268 int err;
269 int close_me = -1; 269 int close_me = -1;
270 270
271#if !ENABLE_PLATFORM_MINGW32
271 if (fd == -1) { 272 if (fd == -1) {
272 if (isatty(STDOUT_FILENO)) 273 if (isatty(STDOUT_FILENO))
273 fd = STDOUT_FILENO; 274 fd = STDOUT_FILENO;
@@ -280,6 +281,7 @@ int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *heigh
280 else 281 else
281 close_me = fd = open("/dev/tty", O_RDONLY); 282 close_me = fd = open("/dev/tty", O_RDONLY);
282 } 283 }
284#endif
283 285
284 win.ws_row = 0; 286 win.ws_row = 0;
285 win.ws_col = 0; 287 win.ws_col = 0;
@@ -303,6 +305,7 @@ int FAST_FUNC get_terminal_width(int fd)
303 return width; 305 return width;
304} 306}
305 307
308#if !ENABLE_PLATFORM_MINGW32
306int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) 309int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
307{ 310{
308 return tcsetattr(STDIN_FILENO, TCSANOW, tp); 311 return tcsetattr(STDIN_FILENO, TCSANOW, tp);
@@ -383,6 +386,7 @@ int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags)
383 get_termios_and_make_raw(fd, &newterm, oldterm, flags); 386 get_termios_and_make_raw(fd, &newterm, oldterm, flags);
384 return tcsetattr(fd, TCSANOW, &newterm); 387 return tcsetattr(fd, TCSANOW, &newterm);
385} 388}
389#endif
386 390
387pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options) 391pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options)
388{ 392{
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index 6cc60f6c0..a0db2b86e 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -513,6 +513,7 @@ void FAST_FUNC xfstat(int fd, struct stat *stat_buf, const char *errmsg)
513 bb_simple_perror_msg_and_die(errmsg); 513 bb_simple_perror_msg_and_die(errmsg);
514} 514}
515 515
516#if !ENABLE_PLATFORM_MINGW32
516// selinux_or_die() - die if SELinux is disabled. 517// selinux_or_die() - die if SELinux is disabled.
517void FAST_FUNC selinux_or_die(void) 518void FAST_FUNC selinux_or_die(void)
518{ 519{
@@ -695,3 +696,4 @@ void FAST_FUNC xvfork_parent_waits_and_exits(void)
695 } 696 }
696 /* Child continues */ 697 /* Child continues */
697} 698}
699#endif /* !ENABLE_PLATFORM_MINGW32 */
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index ead30e499..9ae70de99 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -64,7 +64,7 @@ char* FAST_FUNC xmalloc_follow_symlinks(const char *path)
64 linkpath = xmalloc_readlink(buf); 64 linkpath = xmalloc_readlink(buf);
65 if (!linkpath) { 65 if (!linkpath) {
66 /* not a symlink, or doesn't exist */ 66 /* not a symlink, or doesn't exist */
67 if (errno == EINVAL || errno == ENOENT) 67 if (errno == EINVAL || errno == ENOENT || (ENABLE_PLATFORM_MINGW32 && errno == ENOSYS))
68 return buf; 68 return buf;
69 goto free_buf_ret_null; 69 goto free_buf_ret_null;
70 } 70 }