aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-07-07 14:28:08 +0100
committerRon Yorston <rmy@pobox.com>2016-07-07 14:58:55 +0100
commit613f46218c53c8cabdbf0435653e74e0e0e91e1c (patch)
treeca06a7e7a3e4c861441acb4ea20648d7827fa6ae /libbb
parenta0c61c9492723dd31681f878f9c68c92817a476d (diff)
parent237bedd499c58034a1355484d6d4d906f0180308 (diff)
downloadbusybox-w32-613f46218c53c8cabdbf0435653e74e0e0e91e1c.tar.gz
busybox-w32-613f46218c53c8cabdbf0435653e74e0e0e91e1c.tar.bz2
busybox-w32-613f46218c53c8cabdbf0435653e74e0e0e91e1c.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Kbuild.src1
-rw-r--r--libbb/appletlib.c63
-rw-r--r--libbb/copy_file.c21
-rw-r--r--libbb/getopt32.c82
-rw-r--r--libbb/parse_config.c4
-rw-r--r--libbb/time.c1
6 files changed, 119 insertions, 53 deletions
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 0e14e351e..39d9d907d 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -148,6 +148,7 @@ lib-$(CONFIG_FTPD) += correct_password.o
148lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o 148lib-$(CONFIG_PASSWD) += pw_encrypt.o update_passwd.o obscure.o
149lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o 149lib-$(CONFIG_CHPASSWD) += pw_encrypt.o update_passwd.o
150lib-$(CONFIG_CRYPTPW) += pw_encrypt.o 150lib-$(CONFIG_CRYPTPW) += pw_encrypt.o
151lib-$(CONFIG_MKPASSWD) += pw_encrypt.o
151lib-$(CONFIG_SULOGIN) += pw_encrypt.o correct_password.o 152lib-$(CONFIG_SULOGIN) += pw_encrypt.o correct_password.o
152lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o 153lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o
153lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o 154lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index c528c8a2c..28adf2740 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -52,7 +52,6 @@
52 52
53#include "usage_compressed.h" 53#include "usage_compressed.h"
54 54
55
56#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE 55#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
57static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; 56static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
58#else 57#else
@@ -730,7 +729,7 @@ static void install_links(const char *busybox,
730 } 729 }
731} 730}
732# endif 731# endif
733# else 732# elif ENABLE_BUSYBOX
734static void install_links(const char *busybox UNUSED_PARAM, 733static void install_links(const char *busybox UNUSED_PARAM,
735 int use_symbolic_links UNUSED_PARAM, 734 int use_symbolic_links UNUSED_PARAM,
736 char *custom_install_dir UNUSED_PARAM) 735 char *custom_install_dir UNUSED_PARAM)
@@ -738,6 +737,9 @@ static void install_links(const char *busybox UNUSED_PARAM,
738} 737}
739# endif 738# endif
740 739
740# if ENABLE_BUSYBOX
741static void run_applet_and_exit(const char *name, char **argv) NORETURN;
742
741/* If we were called as "busybox..." */ 743/* If we were called as "busybox..." */
742static int busybox_main(char **argv) 744static int busybox_main(char **argv)
743{ 745{
@@ -828,10 +830,10 @@ static int busybox_main(char **argv)
828 const char *a = applet_names; 830 const char *a = applet_names;
829 dup2(1, 2); 831 dup2(1, 2);
830 while (*a) { 832 while (*a) {
831# if ENABLE_FEATURE_INSTALLER && !ENABLE_PLATFORM_MINGW32 833# if ENABLE_FEATURE_INSTALLER && !ENABLE_PLATFORM_MINGW32
832 if (argv[1][6]) /* --list-full? */ 834 if (argv[1][6]) /* --list-full? */
833 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1); 835 full_write2_str(install_dir[APPLET_INSTALL_LOC(i)] + 1);
834# endif 836# endif
835 full_write2_str(a); 837 full_write2_str(a);
836 full_write2_str("\n"); 838 full_write2_str("\n");
837 i++; 839 i++;
@@ -889,14 +891,10 @@ static int busybox_main(char **argv)
889 * "#!/bin/busybox"-style wrappers */ 891 * "#!/bin/busybox"-style wrappers */
890 applet_name = bb_get_last_path_component_nostrip(argv[0]); 892 applet_name = bb_get_last_path_component_nostrip(argv[0]);
891 run_applet_and_exit(applet_name, argv); 893 run_applet_and_exit(applet_name, argv);
892
893 /*bb_error_msg_and_die("applet not found"); - sucks in printf */
894 full_write2_str(applet_name);
895 full_write2_str(": applet not found\n");
896 /* POSIX: "If a command is not found, the exit status shall be 127" */
897 exit(127);
898} 894}
895# endif
899 896
897# if NUM_APPLETS > 0
900void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) 898void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
901{ 899{
902 int argc = 1; 900 int argc = 1;
@@ -914,15 +912,15 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
914 * "true" and "false" are also special. 912 * "true" and "false" are also special.
915 */ 913 */
916 if (1 914 if (1
917#if defined APPLET_NO_test 915# if defined APPLET_NO_test
918 && applet_no != APPLET_NO_test 916 && applet_no != APPLET_NO_test
919#endif 917# endif
920#if defined APPLET_NO_true 918# if defined APPLET_NO_true
921 && applet_no != APPLET_NO_true 919 && applet_no != APPLET_NO_true
922#endif 920# endif
923#if defined APPLET_NO_false 921# if defined APPLET_NO_false
924 && applet_no != APPLET_NO_false 922 && applet_no != APPLET_NO_false
925#endif 923# endif
926 ) { 924 ) {
927 if (argc == 2 && strcmp(argv[1], "--help") == 0) { 925 if (argc == 2 && strcmp(argv[1], "--help") == 0) {
928 /* Make "foo --help" exit with 0: */ 926 /* Make "foo --help" exit with 0: */
@@ -934,17 +932,28 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
934 check_suid(applet_no); 932 check_suid(applet_no);
935 exit(applet_main[applet_no](argc, argv)); 933 exit(applet_main[applet_no](argc, argv));
936} 934}
935# endif /* NUM_APPLETS > 0 */
937 936
938void FAST_FUNC run_applet_and_exit(const char *name, char **argv) 937static NORETURN void run_applet_and_exit(const char *name, char **argv)
939{ 938{
940 int applet; 939# if ENABLE_BUSYBOX
941
942 if (is_prefixed_with(name, "busybox")) 940 if (is_prefixed_with(name, "busybox"))
943 exit(busybox_main(argv)); 941 exit(busybox_main(argv));
942# endif
943# if NUM_APPLETS > 0
944 /* find_applet_by_name() search is more expensive, so goes second */ 944 /* find_applet_by_name() search is more expensive, so goes second */
945 applet = find_applet_by_name(name); 945 {
946 if (applet >= 0) 946 int applet = find_applet_by_name(name);
947 run_applet_no_and_exit(applet, argv); 947 if (applet >= 0)
948 run_applet_no_and_exit(applet, argv);
949 }
950# endif
951
952 /*bb_error_msg_and_die("applet not found"); - links in printf */
953 full_write2_str(applet_name);
954 full_write2_str(": applet not found\n");
955 /* POSIX: "If a command is not found, the exit status shall be 127" */
956 exit(127);
948} 957}
949 958
950#endif /* !defined(SINGLE_APPLET_MAIN) */ 959#endif /* !defined(SINGLE_APPLET_MAIN) */
@@ -1017,6 +1026,10 @@ int main(int argc UNUSED_PARAM, char **argv)
1017#else 1026#else
1018 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv)); 1027 lbb_prepare("busybox" IF_FEATURE_INDIVIDUAL(, argv));
1019 1028
1029# if !ENABLE_BUSYBOX
1030 if (argv[1] && is_prefixed_with(bb_basename(argv[0]), "busybox"))
1031 argv++;
1032# endif
1020 applet_name = argv[0]; 1033 applet_name = argv[0];
1021 if (applet_name[0] == '-') 1034 if (applet_name[0] == '-')
1022 applet_name++; 1035 applet_name++;
@@ -1048,11 +1061,5 @@ int main(int argc UNUSED_PARAM, char **argv)
1048 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ 1061 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
1049 1062
1050 run_applet_and_exit(applet_name, argv); 1063 run_applet_and_exit(applet_name, argv);
1051
1052 /*bb_error_msg_and_die("applet not found"); - sucks in printf */
1053 full_write2_str(applet_name);
1054 full_write2_str(": applet not found\n");
1055 /* POSIX: "If a command is not found, the exit status shall be 127" */
1056 exit(127);
1057#endif 1064#endif
1058} 1065}
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index a427c441f..c52297376 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -64,6 +64,11 @@ static int ask_and_unlink(const char *dest, int flags)
64 bb_perror_msg("can't create '%s'", dest); 64 bb_perror_msg("can't create '%s'", dest);
65 return -1; /* error */ 65 return -1; /* error */
66 } 66 }
67#if ENABLE_FEATURE_CP_LONG_OPTIONS
68 if (flags & FILEUTILS_RMDEST)
69 if (flags & FILEUTILS_VERBOSE)
70 printf("removed '%s'\n", dest);
71#endif
67 return 1; /* ok (to try again) */ 72 return 1; /* ok (to try again) */
68} 73}
69 74
@@ -213,6 +218,22 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
213 goto preserve_mode_ugid_time; 218 goto preserve_mode_ugid_time;
214 } 219 }
215 220
221 if (dest_exists) {
222 if (flags & FILEUTILS_UPDATE) {
223 if (source_stat.st_mtime <= dest_stat.st_mtime) {
224 return 0; /* source file must be newer */
225 }
226 }
227#if ENABLE_FEATURE_CP_LONG_OPTIONS
228 if (flags & FILEUTILS_RMDEST) {
229 ovr = ask_and_unlink(dest, flags);
230 if (ovr <= 0)
231 return ovr;
232 dest_exists = 0;
233 }
234#endif
235 }
236
216 if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) { 237 if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
217 int (*lf)(const char *oldpath, const char *newpath); 238 int (*lf)(const char *oldpath, const char *newpath);
218 make_links: 239 make_links:
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index ae019b26b..ed9352191 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -17,23 +17,20 @@
17uint32_t 17uint32_t
18getopt32(char **argv, const char *applet_opts, ...) 18getopt32(char **argv, const char *applet_opts, ...)
19 19
20 The command line options must be declared in const char 20 The command line options are passed as the applet_opts string.
21 *applet_opts as a string of chars, for example:
22
23 flags = getopt32(argv, "rnug");
24 21
25 If one of the given options is found, a flag value is added to 22 If one of the given options is found, a flag value is added to
26 the return value (an unsigned long). 23 the return value.
27 24
28 The flag value is determined by the position of the char in 25 The flag value is determined by the position of the char in
29 applet_opts string. For example, in the above case: 26 applet_opts string. For example:
30 27
31 flags = getopt32(argv, "rnug"); 28 flags = getopt32(argv, "rnug");
32 29
33 "r" will add 1 (bit 0) 30 "r" will set 1 (bit 0)
34 "n" will add 2 (bit 1) 31 "n" will set 2 (bit 1)
35 "u" will add 4 (bit 2) 32 "u" will set 4 (bit 2)
36 "g" will add 8 (bit 3) 33 "g" will set 8 (bit 3)
37 34
38 and so on. You can also look at the return value as a bit 35 and so on. You can also look at the return value as a bit
39 field and each option sets one bit. 36 field and each option sets one bit.
@@ -45,7 +42,7 @@ getopt32(char **argv, const char *applet_opts, ...)
45 (options and their parameters will be moved into argv[] 42 (options and their parameters will be moved into argv[]
46 positions prior to argv[optind]). 43 positions prior to argv[optind]).
47 44
48 ":" If one of the options requires an argument, then add a ":" 45 "o:" If one of the options requires an argument, then add a ":"
49 after the char in applet_opts and provide a pointer to store 46 after the char in applet_opts and provide a pointer to store
50 the argument. For example: 47 the argument. For example:
51 48
@@ -58,15 +55,39 @@ getopt32(char **argv, const char *applet_opts, ...)
58 &pointer_to_arg_for_a, &pointer_to_arg_for_b, 55 &pointer_to_arg_for_a, &pointer_to_arg_for_b,
59 &pointer_to_arg_for_c, &pointer_to_arg_for_d); 56 &pointer_to_arg_for_c, &pointer_to_arg_for_d);
60 57
61 The type of the pointer (char* or llist_t*) may be controlled 58 The type of the pointer may be controlled by "o::" or "o+" in
62 by the "::" special separator that is set in the external string 59 the external string opt_complementary (see below for more info).
63 opt_complementary (see below for more info).
64 60
65 "::" If option can have an *optional* argument, then add a "::" 61 "o::" If option can have an *optional* argument, then add a "::"
66 after its char in applet_opts and provide a pointer to store 62 after its char in applet_opts and provide a pointer to store
67 the argument. Note that optional arguments _must_ 63 the argument. Note that optional arguments _must_
68 immediately follow the option: -oparam, not -o param. 64 immediately follow the option: -oparam, not -o param.
69 65
66 "o:+" This means that the parameter for this option is a nonnegative integer.
67 It will be processed with xatoi_positive() - allowed range
68 is 0..INT_MAX.
69
70 int param; // "unsigned param;" will also work
71 getopt32(argv, "p:+", &param);
72
73 "o:*" This means that the option can occur multiple times. Each occurrence
74 will be saved as a llist_t element instead of char*.
75
76 For example:
77 The grep applet can have one or more "-e pattern" arguments.
78 In this case you should use getopt32() as follows:
79
80 llist_t *patterns = NULL;
81
82 (this pointer must be initializated to NULL if the list is empty
83 as required by llist_add_to_end(llist_t **old_head, char *new_item).)
84
85 getopt32(argv, "e:*", &patterns);
86
87 $ grep -e user -e root /etc/passwd
88 root:x:0:0:root:/root:/bin/bash
89 user:x:500:500::/home/user:/bin/bash
90
70 "+" If the first character in the applet_opts string is a plus, 91 "+" If the first character in the applet_opts string is a plus,
71 then option processing will stop as soon as a non-option is 92 then option processing will stop as soon as a non-option is
72 encountered in the argv array. Useful for applets like env 93 encountered in the argv array. Useful for applets like env
@@ -82,7 +103,7 @@ const char *applet_long_options
82 This struct allows you to define long options: 103 This struct allows you to define long options:
83 104
84 static const char applet_longopts[] ALIGN1 = 105 static const char applet_longopts[] ALIGN1 =
85 //"name\0" has_arg val 106 //"name\0" has_arg val
86 "verbose\0" No_argument "v" 107 "verbose\0" No_argument "v"
87 ; 108 ;
88 applet_long_options = applet_longopts; 109 applet_long_options = applet_longopts;
@@ -90,7 +111,7 @@ const char *applet_long_options
90 The last member of struct option (val) typically is set to 111 The last member of struct option (val) typically is set to
91 matching short option from applet_opts. If there is no matching 112 matching short option from applet_opts. If there is no matching
92 char in applet_opts, then: 113 char in applet_opts, then:
93 - return bit have next position after short options 114 - return bit has next position after short options
94 - if has_arg is not "No_argument", use ptr for arg also 115 - if has_arg is not "No_argument", use ptr for arg also
95 - opt_complementary affects it too 116 - opt_complementary affects it too
96 117
@@ -139,8 +160,8 @@ const char *opt_complementary
139 160
140 llist_t *my_b = NULL; 161 llist_t *my_b = NULL;
141 int verbose_level = 0; 162 int verbose_level = 0;
142 opt_complementary = "vv:b::b-c:c-b"; 163 opt_complementary = "vv:b-c:c-b";
143 f = getopt32(argv, "vb:c", &my_b, &verbose_level); 164 f = getopt32(argv, "vb:*c", &my_b, &verbose_level);
144 if (f & 2) // -c after -b unsets -b flag 165 if (f & 2) // -c after -b unsets -b flag
145 while (my_b) dosomething_with(llist_pop(&my_b)); 166 while (my_b) dosomething_with(llist_pop(&my_b));
146 if (my_b) // but llist is stored if -b is specified 167 if (my_b) // but llist is stored if -b is specified
@@ -233,7 +254,7 @@ Special characters:
233 "x--x" Variation of the above, it means that -x option should occur 254 "x--x" Variation of the above, it means that -x option should occur
234 at most once. 255 at most once.
235 256
236 "a+" A plus after a char in opt_complementary means that the parameter 257 "o+" A plus after a char in opt_complementary means that the parameter
237 for this option is a nonnegative integer. It will be processed 258 for this option is a nonnegative integer. It will be processed
238 with xatoi_positive() - allowed range is 0..INT_MAX. 259 with xatoi_positive() - allowed range is 0..INT_MAX.
239 260
@@ -241,7 +262,7 @@ Special characters:
241 opt_complementary = "p+"; 262 opt_complementary = "p+";
242 getopt32(argv, "p:", &param); 263 getopt32(argv, "p:", &param);
243 264
244 "a::" A double colon after a char in opt_complementary means that the 265 "o::" A double colon after a char in opt_complementary means that the
245 option can occur multiple times. Each occurrence will be saved as 266 option can occur multiple times. Each occurrence will be saved as
246 a llist_t element instead of char*. 267 a llist_t element instead of char*.
247 268
@@ -255,12 +276,17 @@ Special characters:
255 as required by llist_add_to_end(llist_t **old_head, char *new_item).) 276 as required by llist_add_to_end(llist_t **old_head, char *new_item).)
256 277
257 opt_complementary = "e::"; 278 opt_complementary = "e::";
258
259 getopt32(argv, "e:", &patterns); 279 getopt32(argv, "e:", &patterns);
280
260 $ grep -e user -e root /etc/passwd 281 $ grep -e user -e root /etc/passwd
261 root:x:0:0:root:/root:/bin/bash 282 root:x:0:0:root:/root:/bin/bash
262 user:x:500:500::/home/user:/bin/bash 283 user:x:500:500::/home/user:/bin/bash
263 284
285 "o+" and "o::" can be handled by "o:+" and "o:*" specifiers
286 in option string (and it is preferred), but this does not work
287 for "long options only" cases, such as tar --exclude=PATTERN,
288 wget --header=HDR cases.
289
264 "a?b" A "?" between an option and a group of options means that 290 "a?b" A "?" between an option and a group of options means that
265 at least one of them is required to occur if the first option 291 at least one of them is required to occur if the first option
266 occurs in preceding command line arguments. 292 occurs in preceding command line arguments.
@@ -359,10 +385,11 @@ getopt32(char **argv, const char *applet_opts, ...)
359 385
360 va_start(p, applet_opts); 386 va_start(p, applet_opts);
361 387
362 c = 0;
363 on_off = complementary; 388 on_off = complementary;
364 memset(on_off, 0, sizeof(complementary)); 389 memset(on_off, 0, sizeof(complementary));
365 390
391 applet_opts = strcpy(alloca(strlen(applet_opts) + 1), applet_opts);
392
366 /* skip bbox extension */ 393 /* skip bbox extension */
367 first_char = applet_opts[0]; 394 first_char = applet_opts[0];
368 if (first_char == '!') 395 if (first_char == '!')
@@ -372,6 +399,7 @@ getopt32(char **argv, const char *applet_opts, ...)
372 s = (const unsigned char *)applet_opts; 399 s = (const unsigned char *)applet_opts;
373 if (*s == '+' || *s == '-') 400 if (*s == '+' || *s == '-')
374 s++; 401 s++;
402 c = 0;
375 while (*s) { 403 while (*s) {
376 if (c >= 32) 404 if (c >= 32)
377 break; 405 break;
@@ -379,6 +407,13 @@ getopt32(char **argv, const char *applet_opts, ...)
379 on_off->switch_on = (1 << c); 407 on_off->switch_on = (1 << c);
380 if (*++s == ':') { 408 if (*++s == ':') {
381 on_off->optarg = va_arg(p, void **); 409 on_off->optarg = va_arg(p, void **);
410 if (s[1] == '+' || s[1] == '*') {
411 /* 'o:+' or 'o:*' */
412 on_off->param_type = (s[1] == '+') ?
413 PARAM_INT : PARAM_LIST;
414 overlapping_strcpy((char*)s + 1, (char*)s + 2);
415 }
416 /* skip possible 'o::' (or 'o:+:' !) */
382 while (*++s == ':') 417 while (*++s == ':')
383 continue; 418 continue;
384 } 419 }
@@ -431,6 +466,7 @@ getopt32(char **argv, const char *applet_opts, ...)
431 applet_long_options = NULL; 466 applet_long_options = NULL;
432 } 467 }
433#endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */ 468#endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */
469
434 for (s = (const unsigned char *)opt_complementary; s && *s; s++) { 470 for (s = (const unsigned char *)opt_complementary; s && *s; s++) {
435 t_complementary *pair; 471 t_complementary *pair;
436 unsigned *pair_switch; 472 unsigned *pair_switch;
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index 1590d9a4c..408439766 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -42,8 +42,8 @@ int parse_main(int argc UNUSED_PARAM, char **argv)
42 int mintokens = 0, ntokens = 128; 42 int mintokens = 0, ntokens = 128;
43 unsigned noout; 43 unsigned noout;
44 44
45 opt_complementary = "-1:n+:m+:f+"; 45 opt_complementary = "-1";
46 noout = 1 & getopt32(argv, "xn:m:d:f:", &ntokens, &mintokens, &delims, &flags); 46 noout = 1 & getopt32(argv, "xn:+m:+d:f:+", &ntokens, &mintokens, &delims, &flags);
47 //argc -= optind; 47 //argc -= optind;
48 argv += optind; 48 argv += optind;
49 49
diff --git a/libbb/time.c b/libbb/time.c
index aa19a47d4..82e6cb172 100644
--- a/libbb/time.c
+++ b/libbb/time.c
@@ -186,6 +186,7 @@ void FAST_FUNC parse_datestr(const char *date_str, struct tm *ptm)
186 } else { 186 } else {
187 bb_error_msg_and_die(bb_msg_invalid_date, date_str); 187 bb_error_msg_and_die(bb_msg_invalid_date, date_str);
188 } 188 }
189 ptm->tm_sec = 0; /* assume zero if [.SS] is not given */
189 if (end == '.') { 190 if (end == '.') {
190 /* xxx.SS */ 191 /* xxx.SS */
191 if (sscanf(strchr(date_str, '.') + 1, "%u%c", 192 if (sscanf(strchr(date_str, '.') + 1, "%u%c",