mirror of
https://codeberg.org/landley/toybox.git
synced 2026-01-26 06:07:55 +00:00
Add TOYFLAG_MOREHELP(CFG_BLAH) to allow annotated help text to drop out
when a second config symbol isn't defined. Use this for various LSM -Z flags, PASSWD_SAD, sort -g, and wget's https support. This replaces the old help text merging scripts/config2help.c used to do. The annotation is a leading !, which removes the next char from usage: lines and the whole line from the rest of the help text. The ! is always removed, and the data it marks is only shown if the argument to TOYFLAG_MOREHELP() is true at compile time. In theory this plumbing should drop out when not used, like lib/args.c.
This commit is contained in:
parent
ab1de187e2
commit
7e099a6d54
@ -72,7 +72,7 @@ void help_exit(char *msg, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
if (!msg) show_help(stdout, 1);
|
||||
if (!msg) show_help(1);
|
||||
else {
|
||||
va_start(va, msg);
|
||||
verror_msg(msg, -1, va);
|
||||
|
||||
@ -28,10 +28,13 @@
|
||||
// Suppress default --help processing
|
||||
#define TOYFLAG_NOHELP (1<<9)
|
||||
#define TOYFLAG_AUTOCONF (1<<10)
|
||||
#define TOYFLAG_TRIMHELP (1<<11)
|
||||
#define TOYFLAG_BIGHELP (1<<12)
|
||||
#define TOYFLAG_MOREHELP(x) (TOYFLAG_TRIMHELP|TOYFLAG_BIGHELP*(x))
|
||||
|
||||
// Line buffered stdout
|
||||
#define TOYFLAG_LINEBUF (1<<11)
|
||||
#define TOYFLAG_NOBUF (1<<12)
|
||||
#define TOYFLAG_LINEBUF (1<<13)
|
||||
#define TOYFLAG_NOBUF (1<<14)
|
||||
|
||||
// Error code to return if argument parsing fails (default 1)
|
||||
#define TOYFLAG_ARGFAIL(x) (x<<24)
|
||||
|
||||
71
main.c
71
main.c
@ -49,7 +49,7 @@ struct toy_list *toy_find(char *name)
|
||||
|
||||
// Figure out whether or not anything is using the option parsing logic,
|
||||
// because the compiler can't figure out whether or not to optimize it away
|
||||
// on its' own. NEED_OPTIONS becomes a constant allowing if() to optimize
|
||||
// on its' own. NEED_OPTIONS becomes a constant allowing if() to optimize
|
||||
// stuff out via dead code elimination.
|
||||
|
||||
#undef NEWTOY
|
||||
@ -60,6 +60,16 @@ static const int NEED_OPTIONS =
|
||||
#include "generated/newtoys.h"
|
||||
0; // Ends the opts || opts || opts...
|
||||
|
||||
// Same trick but with the TRIMHELP plumbing.
|
||||
|
||||
#undef NEWTOY
|
||||
#undef OLDTOY
|
||||
#define NEWTOY(name, opts, flags) ((flags)&TOYFLAG_TRIMHELP) ||
|
||||
#define OLDTOY(name, oldname, flags) ((flags)&TOYFLAG_TRIMHELP) ||
|
||||
static const int NEED_TRIMHELP =
|
||||
#include "generated/newtoys.h"
|
||||
0;
|
||||
|
||||
// Populate help text array
|
||||
|
||||
#undef NEWTOY
|
||||
@ -71,32 +81,31 @@ static const int NEED_OPTIONS =
|
||||
#define OLDTOY(name, oldname, flags) HELP_##oldname "\0"
|
||||
#endif
|
||||
|
||||
#if CFG_TOYBOX_ZHELP
|
||||
#include "generated/zhelp.h"
|
||||
static char *help_data = 0;
|
||||
#else
|
||||
#include "generated/help.h"
|
||||
static const char help_data[] =
|
||||
#include "generated/newtoys.h"
|
||||
;
|
||||
|
||||
#if CFG_TOYBOX_ZHELP
|
||||
#include "generated/zhelp.h"
|
||||
#else
|
||||
static char *zhelp_data = 0;
|
||||
#define zhelp_data help_data
|
||||
#define ZHELP_LEN 0
|
||||
#endif
|
||||
|
||||
void show_help(FILE *out, int flags)
|
||||
void show_help(int flags)
|
||||
{
|
||||
int i = toys.which-toy_list;
|
||||
char *s, *ss, *hd;
|
||||
char *s, *ss;
|
||||
|
||||
if (!CFG_TOYBOX_HELP) return;
|
||||
|
||||
if (CFG_TOYBOX_ZHELP)
|
||||
gunzip_mem(zhelp_data, sizeof(zhelp_data), hd = xmalloc(ZHELP_LEN),
|
||||
gunzip_mem(zhelp_data, sizeof(zhelp_data), help_data = xmalloc(ZHELP_LEN),
|
||||
ZHELP_LEN);
|
||||
else hd = (void *)help_data;
|
||||
|
||||
if (flags & HELP_HEADER)
|
||||
fprintf(out, "Toybox %s"USE_TOYBOX(" multicall binary")"%s\n\n",
|
||||
if (flags&HELP_HEADER)
|
||||
printf("Toybox %s"USE_TOYBOX(" multicall binary")"%s\n\n",
|
||||
toybox_version, (CFG_TOYBOX && i) ? " (see toybox --help)"
|
||||
: " (see https://landley.net/toybox)");
|
||||
|
||||
@ -107,18 +116,44 @@ void show_help(FILE *out, int flags)
|
||||
if (*s != 255) break;
|
||||
i = toy_find(++s)-toy_list;
|
||||
if ((flags & HELP_SEE) && toy_list[i].flags) {
|
||||
if (flags & HELP_HTML) fprintf(out, "See <a href=#%s>%s</a>\n", s, s);
|
||||
else fprintf(out, "%s see %s\n", toys.which->name, s);
|
||||
if (flags & HELP_HTML) printf("See <a href=#%s>%s</a>\n", s, s);
|
||||
else printf("%s see %s\n", toys.which->name, s);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & HELP_USAGE)) fprintf(out, "%s\n", s);
|
||||
else {
|
||||
// Only "help -u" calls HELP_USAGE
|
||||
if (CFG_HELP && (flags&HELP_USAGE)) {
|
||||
strstart(&s, "usage: ");
|
||||
for (ss = s; *ss && *ss!='\n'; ss++);
|
||||
fprintf(out, "%.*s\n", (int)(ss-s), s);
|
||||
printf("%.*s\n", (int)(ss-s), s);
|
||||
} else if (!NEED_TRIMHELP || !(toys.which->flags&TOYFLAG_TRIMHELP)) puts(s);
|
||||
// TRIMHELP lines starting with ! are only displayed with BIGHELP,
|
||||
// and the starting ! is edited out either way.
|
||||
else {
|
||||
int big = toys.which->flags&TOYFLAG_BIGHELP, usage = 1;
|
||||
|
||||
for (; *s; s++) {
|
||||
// For usage: line, chop out individual chars after each !
|
||||
if (usage && *s=='!') {
|
||||
s++;
|
||||
if (!big) continue;
|
||||
}
|
||||
putchar(*s);
|
||||
|
||||
// For other lines, chop out whole lines starting with !
|
||||
if (*s=='\n') {
|
||||
usage = 0;
|
||||
if (s[1]=='!') {
|
||||
s++;
|
||||
if (big) continue;
|
||||
s += strcspn(s, "\n");
|
||||
if (!*s) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +177,7 @@ void check_help(char **arg)
|
||||
toys.which = 0;
|
||||
if (!(toys.which = toy_find(arg[1]))) unknown(arg[1]);
|
||||
}
|
||||
show_help(stdout, HELP_HEADER);
|
||||
show_help(HELP_HEADER);
|
||||
xexit();
|
||||
}
|
||||
|
||||
|
||||
@ -150,8 +150,8 @@ fi
|
||||
|
||||
# Rebuild config.h from .config
|
||||
$SED -En $KCONFIG_CONFIG > "$GENDIR"/config.h \
|
||||
-e 's/^# CONFIG_(.*) is not set.*/#define CFG_\1 0\n#define USE_\1(...)/p;t' \
|
||||
-e 's/^CONFIG_(.*)=y.*/#define CFG_\1 1\n#define USE_\1(...) __VA_ARGS__/p;t'\
|
||||
-e 's/^# CONFIG_(.*) is not set.*/#define CFG_\1 0\n#define USE_\1(...)\n#define SKIP_\1(...) __VA_ARGS__/p;t' \
|
||||
-e 's/^CONFIG_(.*)=y.*/#define CFG_\1 1\n#define USE_\1(...) __VA_ARGS__\n#define SKIP_\1(...)/p;t'\
|
||||
-e 's/^CONFIG_(.*)=/#define CFG_\1 /p' || exit 1
|
||||
|
||||
# Process config.h and newtoys.h to generate FLAG_x macros. Note we must
|
||||
|
||||
2
toys.h
2
toys.h
@ -89,7 +89,7 @@
|
||||
#define HELP_HTML 8 // Output HTML
|
||||
|
||||
struct toy_list *toy_find(char *name);
|
||||
void show_help(FILE *out, int full);
|
||||
void show_help(int full);
|
||||
void check_help(char **arg);
|
||||
void toy_singleinit(struct toy_list *which, char *argv[]);
|
||||
void toy_init(struct toy_list *which, char *argv[]);
|
||||
|
||||
@ -4,27 +4,22 @@
|
||||
*
|
||||
* http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/mknod.html
|
||||
|
||||
USE_MKNOD(NEWTOY(mknod, "<2>4m(mode):"USE_MKNOD_Z("Z:"), TOYFLAG_BIN|TOYFLAG_UMASK))
|
||||
USE_MKNOD(NEWTOY(mknod, "<2>4m(mode):"SKIP_TOYBOX_LSM_NONE("Z:"), TOYFLAG_BIN|TOYFLAG_UMASK|TOYFLAG_MOREHELP(!CFG_TOYBOX_LSM_NONE)))
|
||||
|
||||
config MKNOD
|
||||
bool "mknod"
|
||||
default y
|
||||
help
|
||||
usage: mknod [-m MODE] NAME TYPE [MAJOR MINOR]
|
||||
usage: mknod [-m MODE] ![!-!Z! !C!O!N!T!E!X!T!]! NAME TYPE [MAJOR MINOR]
|
||||
|
||||
Create a special file NAME with a given type. TYPE is b for block device,
|
||||
c or u for character device, p for named pipe (which ignores MAJOR/MINOR).
|
||||
Create new device node NAME. TYPE is b for block device, c for character
|
||||
device, p for named pipe (which ignores MAJOR/MINOR).
|
||||
|
||||
-m Mode (file permissions) of new device, in octal or u+x format
|
||||
!-Z Set security context of new device
|
||||
|
||||
config MKNOD_Z
|
||||
bool
|
||||
default y
|
||||
depends on MKNOD && !TOYBOX_LSM_NONE
|
||||
help
|
||||
usage: mknod [-Z CONTEXT] ...
|
||||
|
||||
-Z Set security context to created file
|
||||
These days devtmpfs usually creates nodes for you. For the historical list,
|
||||
See https://www.kernel.org/pub/linux/docs/lanana/device-list/devices-2.6.txt
|
||||
*/
|
||||
|
||||
#define FOR_mknod
|
||||
@ -49,8 +44,7 @@ void mknod_main(void)
|
||||
minor = atoi(toys.optargs[3]);
|
||||
}
|
||||
|
||||
if (FLAG(Z) && lsm_set_create(TT.Z)==-1)
|
||||
perror_exit("-Z '%s' failed", TT.Z);
|
||||
if (FLAG(Z) && lsm_set_create(TT.Z)==-1) perror_exit("-Z '%s' failed", TT.Z);
|
||||
if (mknod(*toys.optargs, mode|modes[type], dev_makedev(major, minor)))
|
||||
perror_exit_raw(*toys.optargs);
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
*
|
||||
* http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html
|
||||
|
||||
USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
|
||||
USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_MOREHELP(CFG_PASSWD_SAD)))
|
||||
|
||||
config PASSWD
|
||||
bool "passwd"
|
||||
@ -19,6 +19,8 @@ config PASSWD
|
||||
-d Set password to ''
|
||||
-l Lock (disable) account
|
||||
-u Unlock (enable) account
|
||||
!
|
||||
!Checks password is >=6 chars, doesn't include username, and actually changed.
|
||||
|
||||
config PASSWD_SAD
|
||||
bool "Add sad password checking heuristics"
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
* TODO: Add support for Transfer Encoding (gzip|deflate)
|
||||
* TODO: Add support for RFC5987
|
||||
|
||||
USE_WGET(NEWTOY(wget, "<1>1(max-redirect)#<0=20d(debug)O(output-document):p(post-data):", TOYFLAG_USR|TOYFLAG_BIN))
|
||||
USE_WGET(NEWTOY(wget, "<1>1(max-redirect)#<0=20d(debug)O(output-document):p(post-data):", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_MOREHELP(CFG_WGET_LIBTLS|CFG_TOYBOX_LIBCRYPTO)))
|
||||
|
||||
config WGET
|
||||
bool "wget"
|
||||
@ -40,6 +40,7 @@ config WGET
|
||||
|
||||
examples:
|
||||
wget http://www.example.com
|
||||
! wget https://www.example.com
|
||||
|
||||
config WGET_LIBTLS
|
||||
bool "Enable HTTPS support for wget via LibTLS"
|
||||
|
||||
@ -30,12 +30,12 @@ static void do_help(struct toy_list *t)
|
||||
xprintf("<a name=\"%s\"><h1>%s</h1><blockquote><pre>\n", t->name, t->name);
|
||||
|
||||
toys.which = t;
|
||||
show_help(stdout, HELP_USAGE*FLAG(u) + (HELP_SEE|HELP_HTML)*FLAG(h));
|
||||
show_help(HELP_USAGE*FLAG(u) + (HELP_SEE|HELP_HTML)*FLAG(h));
|
||||
|
||||
if (FLAG(h)) xprintf("</blockquote></pre>\n");
|
||||
}
|
||||
|
||||
// Simple help is just toys.which = toy_find("name"); show_help(stdout, 0);
|
||||
// Simple help is just toys.which = toy_find("name"); show_help(0);
|
||||
// but iterating through html output and all commands is a bit more
|
||||
|
||||
void help_main(void)
|
||||
@ -47,7 +47,7 @@ void help_main(void)
|
||||
for (i = 0; i < toys.toycount; i++) {
|
||||
if (!(toy_list[i].flags&(TOYFLAG_NOFORK|TOYFLAG_MAYFORK))) continue;
|
||||
toys.which = toy_list+i;
|
||||
show_help(stdout, HELP_SEE|HELP_USAGE*!toys.optflags);
|
||||
show_help(HELP_SEE|HELP_USAGE*!toys.optflags);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -300,11 +300,11 @@ static void setroute(sa_family_t f, char **argv)
|
||||
else if (!strcmp(*argv, "reinstate")) continue;
|
||||
else if (!strcmp(*argv, "reject")) rtMsg->rtm_type = RTN_UNREACHABLE;
|
||||
else {
|
||||
if (!argv[1]) show_help(stdout, 1);
|
||||
if (!argv[1]) help_exit("need arg");
|
||||
|
||||
if (!strcmp(*argv, "metric")) {
|
||||
unsigned int priority = atolx_range(argv[1], 0, UINT_MAX);
|
||||
addAttr(nlMsg, sizeof(toybuf), &priority, RTA_PRIORITY, sizeof(unsigned int));
|
||||
addAttr(nlMsg, sizeof(toybuf), &priority, RTA_PRIORITY, 4);
|
||||
} else if (!strcmp(*argv, "netmask")) {
|
||||
uint32_t netmask;
|
||||
char *ptr;
|
||||
@ -368,7 +368,7 @@ void route_main(void)
|
||||
if (!*toys.optargs) {
|
||||
if (!TT.A || !strcmp(TT.A, "inet")) display_routes(AF_INET);
|
||||
else if (!strcmp(TT.A, "inet6")) display_routes(AF_INET6);
|
||||
else show_help(stdout, 1);
|
||||
else help_exit("bad -A '%s'", TT.A);
|
||||
} else {
|
||||
if (!TT.A) {
|
||||
if (toys.optc>1 && strchr(toys.optargs[1], ':')) {
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
*
|
||||
* See http://opengroup.org/onlinepubs/9699919799/utilities/id.html
|
||||
|
||||
USE_ID(NEWTOY(id, ">1"USE_ID_Z("Z")"nGgru[!"USE_ID_Z("Z")"Ggu]", TOYFLAG_USR|TOYFLAG_BIN))
|
||||
USE_ID(NEWTOY(id, ">1"SKIP_TOYBOX_LSM_NONE("Z")"nGgru[!"SKIP_TOYBOX_LSM_NONE("Z")"Ggu]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_MOREHELP(!CFG_TOYBOX_LSM_NONE)))
|
||||
USE_GROUPS(NEWTOY(groups, NULL, TOYFLAG_USR|TOYFLAG_BIN))
|
||||
USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_USR|TOYFLAG_BIN))
|
||||
USE_WHOAMI(OLDTOY(whoami, logname, TOYFLAG_USR|TOYFLAG_BIN))
|
||||
@ -15,7 +15,7 @@ config ID
|
||||
bool "id"
|
||||
default y
|
||||
help
|
||||
usage: id [-Ggnru] [USER...]
|
||||
usage: id [-Ggnru!Z] [USER...]
|
||||
|
||||
Print user and group ID.
|
||||
|
||||
@ -24,15 +24,7 @@ config ID
|
||||
-n Print names instead of numeric IDs (to be used with -Ggu)
|
||||
-r Show real ID instead of effective ID
|
||||
-u Show only the effective user ID
|
||||
|
||||
config ID_Z
|
||||
bool
|
||||
default y
|
||||
depends on ID && !TOYBOX_LSM_NONE
|
||||
help
|
||||
usage: id [-Z]
|
||||
|
||||
-Z Show only security context
|
||||
!-Z Show only security context
|
||||
|
||||
config GROUPS
|
||||
bool "groups"
|
||||
|
||||
@ -4,28 +4,20 @@
|
||||
*
|
||||
* See http://opengroup.org/onlinepubs/9699919799/utilities/mkdir.html
|
||||
|
||||
USE_MKDIR(NEWTOY(mkdir, "<1"USE_MKDIR_Z("Z:")"vp(parent)(parents)m:", TOYFLAG_BIN|TOYFLAG_UMASK))
|
||||
USE_MKDIR(NEWTOY(mkdir, "<1"SKIP_TOYBOX_LSM_NONE("Z:")"vp(parent)(parents)m:", TOYFLAG_BIN|TOYFLAG_UMASK|TOYFLAG_MOREHELP(!CFG_TOYBOX_LSM_NONE)))
|
||||
|
||||
config MKDIR
|
||||
bool "mkdir"
|
||||
default y
|
||||
help
|
||||
usage: mkdir [-vp] [-m MODE] [DIR...]
|
||||
usage: mkdir [-vp] ![!-!Z! !c!o!n!t!e!x!t!]! [-m MODE] [DIR...]
|
||||
|
||||
Create one or more directories.
|
||||
|
||||
-m Set permissions of directory to mode
|
||||
-p Make parent directories as needed
|
||||
-v Verbose
|
||||
|
||||
config MKDIR_Z
|
||||
bool
|
||||
default y
|
||||
depends on MKDIR && !TOYBOX_LSM_NONE
|
||||
help
|
||||
usage: [-Z context]
|
||||
|
||||
-Z Set security context
|
||||
!-Z Set security context
|
||||
*/
|
||||
|
||||
#define FOR_mkdir
|
||||
@ -40,9 +32,7 @@ void mkdir_main(void)
|
||||
char **s;
|
||||
mode_t mode = (0777&~toys.old_umask);
|
||||
|
||||
if (CFG_MKDIR_Z && FLAG(Z))
|
||||
if (0>lsm_set_create(TT.Z))
|
||||
perror_exit("-Z '%s' failed", TT.Z);
|
||||
if (FLAG(Z)) if (0>lsm_set_create(TT.Z)) perror_exit("-Z '%s' failed", TT.Z);
|
||||
|
||||
if (TT.m) mode = string_to_mode(TT.m, 0777);
|
||||
|
||||
|
||||
@ -4,24 +4,17 @@
|
||||
*
|
||||
* See http://opengroup.org/onlinepubs/9699919799/utilities/mkfifo.html
|
||||
|
||||
USE_MKFIFO(NEWTOY(mkfifo, "<1"USE_MKFIFO_Z("Z:")"m:", TOYFLAG_USR|TOYFLAG_BIN))
|
||||
USE_MKFIFO(NEWTOY(mkfifo, "<1"SKIP_TOYBOX_LSM_NONE("Z:")"m:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_MOREHELP(!CFG_TOYBOX_LSM_NONE)))
|
||||
|
||||
config MKFIFO
|
||||
bool "mkfifo"
|
||||
default y
|
||||
help
|
||||
usage: mkfifo [NAME...]
|
||||
usage: mkfifo ![!-!Z! !C!O!N!T!E!X!T!]! [NAME...]
|
||||
|
||||
Create FIFOs (named pipes).
|
||||
|
||||
config MKFIFO_Z
|
||||
bool
|
||||
default y
|
||||
depends on MKFIFO && !TOYBOX_LSM_NONE
|
||||
help
|
||||
usage: mkfifo [-Z CONTEXT]
|
||||
|
||||
-Z Security context
|
||||
!
|
||||
!-Z Security context
|
||||
*/
|
||||
|
||||
#define FOR_mkfifo
|
||||
@ -40,9 +33,7 @@ void mkfifo_main(void)
|
||||
TT.mode = 0666;
|
||||
if (FLAG(m)) TT.mode = string_to_mode(TT.m, 0);
|
||||
|
||||
if (CFG_MKFIFO_Z && FLAG(Z))
|
||||
if (0>lsm_set_create(TT.Z))
|
||||
perror_exit("-Z '%s' failed", TT.Z);
|
||||
if (FLAG(Z)) if (0>lsm_set_create(TT.Z)) perror_exit("-Z '%s' failed", TT.Z);
|
||||
|
||||
for (s = toys.optargs; *s; s++)
|
||||
if (mknod(*s, S_IFIFO | TT.mode, 0) < 0) perror_msg_raw(*s);
|
||||
|
||||
@ -7,51 +7,42 @@
|
||||
* Deviations from POSIX: Lots.
|
||||
* We invented -x
|
||||
|
||||
USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMCcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
|
||||
USE_SORT(NEWTOY(sort, USE_TOYBOX_FLOAT("g")"S:T:m" "o:k*t:" "xVbMCcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_MOREHELP(CFG_TOYBOX_FLOAT)))
|
||||
|
||||
config SORT
|
||||
bool "sort"
|
||||
default y
|
||||
help
|
||||
usage: sort [-runbCcdfiMsxVz] [FILE...] [-k#[,#[x]] [-t X]] [-o FILE]
|
||||
usage: sort [-bCcdf!giMnrsuxVz] [FILE...] [-k#[,#[x]] [-t X]] [-o FILE]
|
||||
|
||||
Sort all lines of text from input files (or stdin) to stdout.
|
||||
|
||||
-r Reverse
|
||||
-u Unique lines only
|
||||
-n Numeric order (instead of alphabetical)
|
||||
|
||||
-b Ignore leading blanks (or trailing blanks in second part of key)
|
||||
-C Check whether input is sorted
|
||||
-c Warn if input is unsorted
|
||||
-d Dictionary order (use alphanumeric and whitespace chars only)
|
||||
-f Force uppercase (case insensitive sort)
|
||||
!-g General numeric sort (double precision with nan and inf)
|
||||
-i Ignore nonprinting characters
|
||||
-k Sort by "key" (see below)
|
||||
-k Sort by KEY (see below)
|
||||
-M Month sort (jan, feb, etc)
|
||||
-n Numeric order (instead of alphabetical)
|
||||
-o Output to FILE instead of stdout
|
||||
-r Reverse
|
||||
-s Skip fallback sort (only sort with keys)
|
||||
-t Use a key separator other than whitespace
|
||||
-u Unique lines only
|
||||
-x Hexadecimal numerical sort
|
||||
-V Version numbers (name-1.234-rc6.5b.tgz)
|
||||
-z Zero (null) terminated lines
|
||||
|
||||
Sorting by key looks at a subset of the words on each line. -k2 uses the
|
||||
Sorting by KEY looks at a subset of the words on each line. -k2 uses the
|
||||
second word to the end of the line, -k2,2 looks at only the second word,
|
||||
-k2,4 looks from the start of the second to the end of the fourth word.
|
||||
-k2.4,5 starts from the fourth character of the second word, to the end
|
||||
of the fifth word. Negative values count from the end. Specifying multiple
|
||||
keys uses the later keys as tie breakers, in order. A type specifier
|
||||
appended to a sort key (such as -2,2n) applies only to sorting that key.
|
||||
|
||||
config SORT_FLOAT
|
||||
bool
|
||||
default y
|
||||
depends on TOYBOX_FLOAT
|
||||
help
|
||||
usage: sort [-g]
|
||||
|
||||
-g General numeric sort (double precision with nan and inf)
|
||||
*/
|
||||
|
||||
#define FOR_sort
|
||||
@ -179,7 +170,7 @@ static struct sort_key *add_key(void)
|
||||
// Perform actual comparison
|
||||
static int compare_values(int flags, char *x, char *y)
|
||||
{
|
||||
if (CFG_SORT_FLOAT && (flags & FLAG_g)) {
|
||||
if (CFG_TOYBOX_FLOAT && (flags & FLAG_g)) {
|
||||
char *xx,*yy;
|
||||
double dx = strtod(x,&xx), dy = strtod(y,&yy);
|
||||
int xinf, yinf;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user