]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/strutils.c
2 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
3 * Copyright (C) 2010 Davidlohr Bueso <dave@gnu.org>
5 * No copyright is claimed. This code is in the public domain; do with
21 #include "pathnames.h"
23 static int STRTOXX_EXIT_CODE
= EXIT_FAILURE
;
25 void strutils_set_exitcode(int ex
) {
26 STRTOXX_EXIT_CODE
= ex
;
29 static int do_scale_by_power (uintmax_t *x
, int base
, int power
)
32 if (UINTMAX_MAX
/ base
< *x
)
40 * strtosize() - convert string to size (uintmax_t).
45 * where X = {K,M,G,T,P,E,Z,Y}
46 * or X = {k,m,g,t,p,e} (undocumented for backward compatibility only)
52 * where X = {K,M,G,T,P,E,Z,Y}
56 * The optional 'power' variable returns number associated with used suffix
57 * {K,M,G,T,P,E,Z,Y} = {1,2,3,4,5,6,7,8}.
59 * The function also supports decimal point, for example:
63 * Note that the function does not accept numbers with '-' (negative sign)
66 int parse_size(const char *str
, uintmax_t *res
, int *power
)
70 uintmax_t x
, frac
= 0;
71 int base
= 1024, rc
= 0, pwr
= 0, frac_zeros
= 0;
73 static const char *suf
= "KMGTPEZY";
74 static const char *suf2
= "kmgtpezy";
84 /* Only positive numbers are acceptable
86 * Note that this check is not perfect, it would be better to
87 * use lconv->negative_sign. But coreutils use the same solution,
88 * so it's probably good enough...
91 while (isspace((unsigned char) *p
))
98 errno
= 0, end
= NULL
;
99 x
= strtoumax(str
, &end
, 0);
102 (errno
!= 0 && (x
== UINTMAX_MAX
|| x
== 0))) {
103 rc
= errno
? -errno
: -EINVAL
;
107 goto done
; /* without suffix */
111 * Check size suffixes
114 if (*(p
+ 1) == 'i' && (*(p
+ 2) == 'B' || *(p
+ 2) == 'b') && !*(p
+ 3))
115 base
= 1024; /* XiB, 2^N */
116 else if ((*(p
+ 1) == 'B' || *(p
+ 1) == 'b') && !*(p
+ 2))
117 base
= 1000; /* XB, 10^N */
119 struct lconv
const *l
= localeconv();
120 const char *dp
= l
? l
->decimal_point
: NULL
;
121 size_t dpsz
= dp
? strlen(dp
) : 0;
123 if (frac
== 0 && *p
&& dp
&& strncmp(dp
, p
, dpsz
) == 0) {
124 const char *fstr
= p
+ dpsz
;
126 for (p
= fstr
; *p
== '0'; p
++)
129 if (isdigit(*fstr
)) {
130 errno
= 0, end
= NULL
;
131 frac
= strtoumax(fstr
, &end
, 0);
133 (errno
!= 0 && (frac
== UINTMAX_MAX
|| frac
== 0))) {
134 rc
= errno
? -errno
: -EINVAL
;
140 if (frac
&& (!end
|| !*end
)) {
142 goto err
; /* without suffix, but with frac */
148 goto err
; /* unexpected suffix */
151 sp
= strchr(suf
, *p
);
153 pwr
= (sp
- suf
) + 1;
155 sp
= strchr(suf2
, *p
);
157 pwr
= (sp
- suf2
) + 1;
164 rc
= do_scale_by_power(&x
, base
, pwr
);
169 uintmax_t frac_div
= 10, frac_poz
= 1, frac_base
= 1;
171 /* mega, giga, ... */
172 do_scale_by_power(&frac_base
, base
, pwr
);
174 /* maximal divisor for last digit (e.g. for 0.05 is
175 * frac_div=100, for 0.054 is frac_div=1000, etc.)
177 * Reduce frac if too large.
179 while (frac_div
< frac
) {
180 if (frac_div
<= UINTMAX_MAX
/10)
186 /* 'frac' is without zeros (5 means 0.5 as well as 0.05) */
187 for (i
= 0; i
< frac_zeros
; i
++) {
188 if (frac_div
<= UINTMAX_MAX
/10)
195 * Go backwardly from last digit and add to result what the
196 * digit represents in the frac_base. For example 0.25G
198 * 5 means 1GiB / (100/5)
199 * 2 means 1GiB / (10/2)
202 unsigned int seg
= frac
% 10; /* last digit of the frac */
203 uintmax_t seg_div
= frac_div
/ frac_poz
; /* what represents the segment 1000, 100, .. */
205 frac
/= 10; /* remove last digit from frac */
208 if (seg
&& seg_div
/ seg
)
209 x
+= frac_base
/ (seg_div
/ seg
);
220 int strtosize(const char *str
, uintmax_t *res
)
222 return parse_size(str
, res
, NULL
);
225 int isdigit_strend(const char *str
, const char **end
)
229 for (p
= str
; p
&& *p
&& isdigit((unsigned char) *p
); p
++);
233 return p
&& p
> str
&& !*p
;
236 int isxdigit_strend(const char *str
, const char **end
)
240 for (p
= str
; p
&& *p
&& isxdigit((unsigned char) *p
); p
++);
245 return p
&& p
> str
&& !*p
;
249 * parse_switch(argv[i], "on", "off", "yes", "no", NULL);
251 int parse_switch(const char *arg
, const char *errmesg
, ...)
256 va_start(ap
, errmesg
);
258 a
= va_arg(ap
, char *);
261 b
= va_arg(ap
, char *);
265 if (strcmp(arg
, a
) == 0) {
270 if (strcmp(arg
, b
) == 0) {
277 errx(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, arg
);
281 void *mempcpy(void *restrict dest
, const void *restrict src
, size_t n
)
283 return ((char *)memcpy(dest
, src
, n
)) + n
;
288 size_t strnlen(const char *s
, size_t maxlen
)
292 for (i
= 0; i
< maxlen
; i
++) {
301 char *strnchr(const char *s
, size_t maxlen
, int c
)
303 for (; maxlen
-- && *s
!= '\0'; ++s
)
311 char *strndup(const char *s
, size_t n
)
313 size_t len
= strnlen(s
, n
);
314 char *new = malloc((len
+ 1) * sizeof(char));
318 return (char *) memcpy(new, s
, len
);
322 static uint32_t _strtou32_or_err(const char *str
, const char *errmesg
, int base
);
323 static uint64_t _strtou64_or_err(const char *str
, const char *errmesg
, int base
);
325 int16_t strtos16_or_err(const char *str
, const char *errmesg
)
327 int32_t num
= strtos32_or_err(str
, errmesg
);
329 if (num
< INT16_MIN
|| num
> INT16_MAX
) {
331 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
336 static uint16_t _strtou16_or_err(const char *str
, const char *errmesg
, int base
)
338 uint32_t num
= _strtou32_or_err(str
, errmesg
, base
);
340 if (num
> UINT16_MAX
) {
342 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
347 uint16_t strtou16_or_err(const char *str
, const char *errmesg
)
349 return _strtou16_or_err(str
, errmesg
, 10);
352 uint16_t strtox16_or_err(const char *str
, const char *errmesg
)
354 return _strtou16_or_err(str
, errmesg
, 16);
357 int32_t strtos32_or_err(const char *str
, const char *errmesg
)
359 int64_t num
= strtos64_or_err(str
, errmesg
);
361 if (num
< INT32_MIN
|| num
> INT32_MAX
) {
363 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
368 static uint32_t _strtou32_or_err(const char *str
, const char *errmesg
, int base
)
370 uint64_t num
= _strtou64_or_err(str
, errmesg
, base
);
372 if (num
> UINT32_MAX
) {
374 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
379 uint32_t strtou32_or_err(const char *str
, const char *errmesg
)
381 return _strtou32_or_err(str
, errmesg
, 10);
384 uint32_t strtox32_or_err(const char *str
, const char *errmesg
)
386 return _strtou32_or_err(str
, errmesg
, 16);
389 int64_t strtos64_or_err(const char *str
, const char *errmesg
)
395 if (str
== NULL
|| *str
== '\0')
397 num
= strtoimax(str
, &end
, 10);
399 if (errno
|| str
== end
|| (end
&& *end
))
405 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
407 errx(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
410 static uint64_t _strtou64_or_err(const char *str
, const char *errmesg
, int base
)
416 if (str
== NULL
|| *str
== '\0')
418 num
= strtoumax(str
, &end
, base
);
420 if (errno
|| str
== end
|| (end
&& *end
))
426 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
428 errx(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
431 uint64_t strtou64_or_err(const char *str
, const char *errmesg
)
433 return _strtou64_or_err(str
, errmesg
, 10);
436 uint64_t strtox64_or_err(const char *str
, const char *errmesg
)
438 return _strtou64_or_err(str
, errmesg
, 16);
441 double strtod_or_err(const char *str
, const char *errmesg
)
447 if (str
== NULL
|| *str
== '\0')
449 num
= strtod(str
, &end
);
451 if (errno
|| str
== end
|| (end
&& *end
))
457 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
459 errx(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
462 long strtol_or_err(const char *str
, const char *errmesg
)
468 if (str
== NULL
|| *str
== '\0')
470 num
= strtol(str
, &end
, 10);
472 if (errno
|| str
== end
|| (end
&& *end
))
478 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
480 errx(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
483 unsigned long strtoul_or_err(const char *str
, const char *errmesg
)
489 if (str
== NULL
|| *str
== '\0')
491 num
= strtoul(str
, &end
, 10);
493 if (errno
|| str
== end
|| (end
&& *end
))
499 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
501 errx(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
504 uintmax_t strtosize_or_err(const char *str
, const char *errmesg
)
508 if (strtosize(str
, &num
) == 0)
512 err(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
514 errx(STRTOXX_EXIT_CODE
, "%s: '%s'", errmesg
, str
);
518 void strtotimeval_or_err(const char *str
, struct timeval
*tv
, const char *errmesg
)
522 user_input
= strtod_or_err(str
, errmesg
);
523 tv
->tv_sec
= (time_t) user_input
;
524 tv
->tv_usec
= (long)((user_input
- tv
->tv_sec
) * 1000000);
528 * Converts stat->st_mode to ls(1)-like mode string. The size of "str" must
531 char *xstrmode(mode_t mode
, char *str
)
533 unsigned short i
= 0;
537 else if (S_ISLNK(mode
))
539 else if (S_ISCHR(mode
))
541 else if (S_ISBLK(mode
))
543 else if (S_ISSOCK(mode
))
545 else if (S_ISFIFO(mode
))
547 else if (S_ISREG(mode
))
550 str
[i
++] = mode
& S_IRUSR
? 'r' : '-';
551 str
[i
++] = mode
& S_IWUSR
? 'w' : '-';
552 str
[i
++] = (mode
& S_ISUID
553 ? (mode
& S_IXUSR
? 's' : 'S')
554 : (mode
& S_IXUSR
? 'x' : '-'));
555 str
[i
++] = mode
& S_IRGRP
? 'r' : '-';
556 str
[i
++] = mode
& S_IWGRP
? 'w' : '-';
557 str
[i
++] = (mode
& S_ISGID
558 ? (mode
& S_IXGRP
? 's' : 'S')
559 : (mode
& S_IXGRP
? 'x' : '-'));
560 str
[i
++] = mode
& S_IROTH
? 'r' : '-';
561 str
[i
++] = mode
& S_IWOTH
? 'w' : '-';
562 str
[i
++] = (mode
& S_ISVTX
563 ? (mode
& S_IXOTH
? 't' : 'T')
564 : (mode
& S_IXOTH
? 'x' : '-'));
571 * returns exponent (2^x=n) in range KiB..EiB (2^10..2^60)
573 static int get_exp(uint64_t n
)
577 for (shft
= 10; shft
<= 60; shft
+= 10) {
578 if (n
< (1ULL << shft
))
584 char *size_to_human_string(int options
, uint64_t bytes
)
589 const char *letters
= "BKMGTPE";
590 char suffix
[sizeof(" KiB")], *psuf
= suffix
;
593 if (options
& SIZE_SUFFIX_SPACE
)
597 exp
= get_exp(bytes
);
598 c
= *(letters
+ (exp
? exp
/ 10 : 0));
599 dec
= exp
? bytes
/ (1ULL << exp
) : bytes
;
600 frac
= exp
? bytes
% (1ULL << exp
) : 0;
604 if ((options
& SIZE_SUFFIX_3LETTER
) && (c
!= 'B')) {
611 /* fprintf(stderr, "exp: %d, unit: %c, dec: %d, frac: %jd\n",
612 * exp, suffix[0], dec, frac);
617 /* get 3 digits after decimal point */
618 if (frac
>= UINT64_MAX
/ 1000)
619 frac
= ((frac
/ 1024) * 1000) / (1ULL << (exp
- 10)) ;
621 frac
= (frac
* 1000) / (1ULL << (exp
)) ;
623 if (options
& SIZE_DECIMAL_2DIGITS
) {
624 /* round 4/5 and keep 2 digits after decimal point */
625 frac
= (frac
+ 5) / 10 ;
627 /* round 4/5 and keep 1 digit after decimal point */
628 frac
= ((frac
+ 50) / 100) * 10 ;
631 /* rounding could have overflowed */
639 struct lconv
const *l
= localeconv();
640 char *dp
= l
? l
->decimal_point
: NULL
;
646 len
= snprintf(buf
, sizeof(buf
), "%d%s%02" PRIu64
, dec
, dp
, frac
);
647 if (len
> 0 && (size_t) len
< sizeof(buf
)) {
648 /* remove potential extraneous zero */
649 if (buf
[len
- 1] == '0')
652 xstrncpy(buf
+len
, suffix
, sizeof(buf
) - len
);
654 *buf
= '\0'; /* snprintf error */
656 snprintf(buf
, sizeof(buf
), "%d%s", dec
, suffix
);
662 * Parses comma delimited list to array with IDs, for example:
664 * "aaa,bbb,ccc" --> ary[0] = FOO_AAA;
668 * The function name2id() provides conversion from string to ID.
670 * Returns: >= 0 : number of items added to ary[]
671 * -1 : parse error or unknown item
674 int string_to_idarray(const char *list
, int ary
[], size_t arysz
,
675 int (name2id
)(const char *, size_t))
677 const char *begin
= NULL
, *p
;
680 if (!list
|| !*list
|| !ary
|| !arysz
|| !name2id
)
683 for (p
= list
; p
&& *p
; p
++) {
684 const char *end
= NULL
;
690 begin
= p
; /* begin of the column name */
692 end
= p
; /* terminate the name */
693 if (*(p
+ 1) == '\0')
694 end
= p
+ 1; /* end of string */
700 id
= name2id(begin
, end
- begin
);
712 * Parses the array like string_to_idarray but if format is "+aaa,bbb"
713 * it adds fields to array instead of replacing them.
715 int string_add_to_idarray(const char *list
, int ary
[], size_t arysz
,
716 size_t *ary_pos
, int (name2id
)(const char *, size_t))
718 const char *list_add
;
721 if (!list
|| !*list
|| !ary_pos
|| *ary_pos
> arysz
)
731 r
= string_to_idarray(list_add
, &ary
[*ary_pos
], arysz
- *ary_pos
, name2id
);
738 * LIST ::= <item> [, <item>]
740 * The <item> is translated to 'id' by name2id() function and the 'id' is used
741 * as a position in the 'ary' bit array. It means that the 'id' has to be in
742 * range <0..N> where N < sizeof(ary) * NBBY.
744 * Returns: 0 on success, <0 on error.
746 int string_to_bitarray(const char *list
,
748 int (*name2bit
)(const char *, size_t))
750 const char *begin
= NULL
, *p
;
752 if (!list
|| !name2bit
|| !ary
)
755 for (p
= list
; p
&& *p
; p
++) {
756 const char *end
= NULL
;
760 begin
= p
; /* begin of the level name */
762 end
= p
; /* terminate the name */
763 if (*(p
+ 1) == '\0')
764 end
= p
+ 1; /* end of string */
770 bit
= name2bit(begin
, end
- begin
);
782 * LIST ::= <item> [, <item>]
784 * The <item> is translated to 'id' by name2flag() function and the flags is
787 * Returns: 0 on success, <0 on error.
789 int string_to_bitmask(const char *list
,
791 long (*name2flag
)(const char *, size_t))
793 const char *begin
= NULL
, *p
;
795 if (!list
|| !name2flag
|| !mask
)
798 for (p
= list
; p
&& *p
; p
++) {
799 const char *end
= NULL
;
803 begin
= p
; /* begin of the level name */
805 end
= p
; /* terminate the name */
806 if (*(p
+ 1) == '\0')
807 end
= p
+ 1; /* end of string */
813 flag
= name2flag(begin
, end
- begin
);
815 return flag
; /* error */
825 * Parse the lower and higher values in a string containing
826 * "lower:higher" or "lower-higher" format. Note that either
827 * the lower or the higher values may be missing, and the def
828 * value will be assigned to it by default.
830 * Returns: 0 on success, <0 on error.
832 int parse_range(const char *str
, int *lower
, int *upper
, int def
)
839 *upper
= *lower
= def
;
842 if (*str
== ':') { /* <:N> */
844 *upper
= strtol(str
, &end
, 10);
845 if (errno
|| !end
|| *end
|| end
== str
)
848 *upper
= *lower
= strtol(str
, &end
, 10);
849 if (errno
|| !end
|| end
== str
)
852 if (*end
== ':' && !*(end
+ 1)) /* <M:> */
854 else if (*end
== '-' || *end
== ':') { /* <M:N> <M-N> */
858 *upper
= strtol(str
, &end
, 10);
860 if (errno
|| !end
|| *end
|| end
== str
)
867 static const char *next_path_segment(const char *str
, size_t *sz
)
869 const char *start
, *p
;
873 while (start
&& *start
== '/' && *(start
+ 1) == '/')
876 if (!start
|| !*start
)
879 for (*sz
= 1, p
= start
+ 1; *p
&& *p
!= '/'; p
++) {
886 int streq_paths(const char *a
, const char *b
)
890 const char *a_seg
= next_path_segment(a
, &a_sz
);
891 const char *b_seg
= next_path_segment(b
, &b_sz
);
894 fprintf(stderr, "A>>>(%zu) '%s'\n", a_sz, a_seg);
895 fprintf(stderr, "B>>>(%zu) '%s'\n", b_sz, b_seg);
898 /* end of the path */
899 if (a_sz
+ b_sz
== 0)
902 /* ignore tailing slash */
903 if (a_sz
+ b_sz
== 1 &&
904 ((a_seg
&& *a_seg
== '/') || (b_seg
&& *b_seg
== '/')))
907 if (!a_seg
|| !b_seg
)
909 if (a_sz
!= b_sz
|| strncmp(a_seg
, b_seg
, a_sz
) != 0)
919 char *strnappend(const char *s
, const char *suffix
, size_t b
)
927 return strndup(suffix
, b
);
935 if (b
> ((size_t) -1) - a
)
938 r
= malloc(a
+ b
+ 1);
943 memcpy(r
+ a
, suffix
, b
);
949 char *strappend(const char *s
, const char *suffix
)
951 return strnappend(s
, suffix
, suffix
? strlen(suffix
) : 0);
954 char *strfappend(const char *s
, const char *format
, ...)
960 va_start(ap
, format
);
961 sz
= vasprintf(&val
, format
, ap
);
967 res
= strnappend(s
, val
, sz
);
972 static size_t strcspn_escaped(const char *s
, const char *reject
)
977 for (n
=0; s
[n
]; n
++) {
980 else if (s
[n
] == '\\')
982 else if (strchr(reject
, s
[n
]))
986 /* if s ends in \, return index of previous char */
990 /* Split a string into words. */
991 const char *split(const char **state
, size_t *l
, const char *separator
, int quoted
)
998 assert(**state
== '\0');
1002 current
+= strspn(current
, separator
);
1008 if (quoted
&& strchr("\'\"", *current
)) {
1009 char quotechars
[2] = {*current
, '\0'};
1011 *l
= strcspn_escaped(current
+ 1, quotechars
);
1012 if (current
[*l
+ 1] == '\0' || current
[*l
+ 1] != quotechars
[0] ||
1013 (current
[*l
+ 2] && !strchr(separator
, current
[*l
+ 2]))) {
1014 /* right quote missing or garbage at the end */
1018 *state
= current
++ + *l
+ 2;
1019 } else if (quoted
) {
1020 *l
= strcspn_escaped(current
, separator
);
1021 if (current
[*l
] && !strchr(separator
, current
[*l
])) {
1022 /* unfinished escape */
1026 *state
= current
+ *l
;
1028 *l
= strcspn(current
, separator
);
1029 *state
= current
+ *l
;
1035 /* Rewind file pointer forward to new line. */
1036 int skip_fline(FILE *fp
)
1041 if ((ch
= fgetc(fp
)) == EOF
)
1048 #ifdef TEST_PROGRAM_STRUTILS
1057 static int test_strdup_to_member(int argc
, char *argv
[])
1062 return EXIT_FAILURE
;
1064 xx
= calloc(1, sizeof(*xx
));
1068 strdup_to_struct_member(xx
, name
, argv
[1]);
1069 strdup_to_struct_member(xx
, value
, argv
[2]);
1071 if (strcmp(xx
->name
, argv
[1]) != 0 &&
1072 strcmp(xx
->value
, argv
[2]) != 0)
1073 errx(EXIT_FAILURE
, "strdup_to_struct_member() failed");
1075 printf("1: '%s', 2: '%s'\n", xx
->name
, xx
->value
);
1080 return EXIT_SUCCESS
;
1083 static int test_strutils_sizes(int argc
, char *argv
[])
1086 char *hum1
, *hum2
, *hum3
;
1089 return EXIT_FAILURE
;
1091 if (strtosize(argv
[1], &size
))
1092 errx(EXIT_FAILURE
, "invalid size '%s' value", argv
[1]);
1094 hum1
= size_to_human_string(SIZE_SUFFIX_1LETTER
, size
);
1095 hum2
= size_to_human_string(SIZE_SUFFIX_3LETTER
|
1096 SIZE_SUFFIX_SPACE
, size
);
1097 hum3
= size_to_human_string(SIZE_SUFFIX_3LETTER
|
1099 SIZE_DECIMAL_2DIGITS
, size
);
1101 printf("%25s : %20ju : %8s : %12s : %13s\n", argv
[1], size
, hum1
, hum2
, hum3
);
1106 return EXIT_SUCCESS
;
1109 static int test_strutils_cmp_paths(int argc
, char *argv
[])
1111 int rc
= streq_paths(argv
[1], argv
[2]);
1114 return EXIT_FAILURE
;
1116 printf("%s: '%s' '%s'\n", rc
== 1 ? "YES" : "NOT", argv
[1], argv
[2]);
1117 return EXIT_SUCCESS
;
1120 int main(int argc
, char *argv
[])
1122 if (argc
== 3 && strcmp(argv
[1], "--size") == 0)
1123 return test_strutils_sizes(argc
- 1, argv
+ 1);
1125 if (argc
== 4 && strcmp(argv
[1], "--cmp-paths") == 0)
1126 return test_strutils_cmp_paths(argc
- 1, argv
+ 1);
1128 if (argc
== 4 && strcmp(argv
[1], "--strdup-member") == 0)
1129 return test_strdup_to_member(argc
- 1, argv
+ 1);
1131 fprintf(stderr
, "usage: %1$s --size <number>[suffix]\n"
1132 " %1$s --cmp-paths <path> <path>\n"
1133 " %1$s --strdup-member <str> <str>\n",
1136 return EXIT_FAILURE
;
1138 #endif /* TEST_PROGRAM_STRUTILS */