aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2017-06-19 12:47:01 -0700
committerElliott Hughes <enh@google.com>2017-06-19 13:43:50 -0700
commitf353b240a5e39ca3916362a08c5e4f61c1624dd6 (patch)
tree53fdf77f25724ab8ff0e4d6342b94c40f7143a37
parentfe3d63b2690993d2bd6b11589a7c4bf1c285b7c1 (diff)
parentf5907c9546fb25acd95133f2243f210408fa1505 (diff)
downloadtoybox-f353b240a5e39ca3916362a08c5e4f61c1624dd6.tar.gz
Merge remote-tracking branch 'toybox/master' into HEAD
Change-Id: If21b4f8a327f584912c9021d9792031e6d79c065
-rw-r--r--Android.mk2
-rw-r--r--README9
-rw-r--r--generated/flags.h24
-rw-r--r--generated/globals.h25
-rw-r--r--generated/help.h20
-rw-r--r--generated/newtoys.h6
-rw-r--r--lib/args.c22
-rw-r--r--lib/lib.c5
-rw-r--r--lib/portability.h2
-rw-r--r--scripts/config2help.c42
-rw-r--r--toys/lsb/dmesg.c182
-rw-r--r--toys/pending/dmesg.c190
-rw-r--r--toys/posix/cpio.c15
-rw-r--r--toys/posix/grep.c62
-rw-r--r--toys/posix/ps.c47
-rwxr-xr-xwww/conduct.html32
-rw-r--r--www/header.html1
17 files changed, 387 insertions, 299 deletions
diff --git a/Android.mk b/Android.mk
index 971d8736..8f3698dc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -67,6 +67,7 @@ common_SRC_FILES := \
toys/android/setenforce.c \
toys/android/setprop.c \
toys/android/start.c \
+ toys/lsb/dmesg.c \
toys/lsb/hostname.c \
toys/lsb/killall.c \
toys/lsb/md5sum.c \
@@ -139,7 +140,6 @@ common_SRC_FILES := \
toys/other/yes.c \
toys/pending/dd.c \
toys/pending/diff.c \
- toys/pending/dmesg.c \
toys/pending/expr.c \
toys/pending/getfattr.c \
toys/pending/gzip.c \
diff --git a/README b/README
index 5823309c..eebe7b7d 100644
--- a/README
+++ b/README
@@ -167,12 +167,3 @@ upstream first (into vanilla toybox, with discussion on the toybox mailing
list) and then be pulled into android's toybox repo from there. (They
generally resync on fridays). The exception is patches to their build scripts
(Android.mk and the checked-in generated/* files) which go directly to AOSP.
-
---- Code of conduct
-
-We're using twitter's https://engineering.twitter.com/opensource/code-of-conduct
-except email rob@landley.net with complaints.
-
-(Yes, I try to pay more attention to marginalized programmers, which somehow
-manages to include 51% of the population. If somebody has to be three times as
-good to get half the recognition, why WOULDN'T you adjust for that?)
diff --git a/generated/flags.h b/generated/flags.h
index 6184f352..a240db12 100644
--- a/generated/flags.h
+++ b/generated/flags.h
@@ -354,9 +354,9 @@
#undef FLAG_preserve
#endif
-// cpio (no-preserve-owner)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF] (no-preserve-owner)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]
+// cpio (no-preserve-owner)(trailer)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF] (no-preserve-owner)(trailer)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]
#undef OPTSTR_cpio
-#define OPTSTR_cpio "(no-preserve-owner)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]"
+#define OPTSTR_cpio "(no-preserve-owner)(trailer)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]"
#ifdef CLEANUP_cpio
#undef CLEANUP_cpio
#undef FOR_cpio
@@ -371,6 +371,7 @@
#undef FLAG_u
#undef FLAG_d
#undef FLAG_m
+#undef FLAG_trailer
#undef FLAG_no_preserve_owner
#endif
@@ -572,9 +573,9 @@
#undef FOR_dirname
#endif
-// dmesg w(follow)CSTtrs#<1n#c[!Ttr][!Cc] w(follow)CSTtrs#<1n#c[!Ttr][!Cc]
+// dmesg w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw] w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]
#undef OPTSTR_dmesg
-#define OPTSTR_dmesg "w(follow)CSTtrs#<1n#c[!Ttr][!Cc]"
+#define OPTSTR_dmesg "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]"
#ifdef CLEANUP_dmesg
#undef CLEANUP_dmesg
#undef FOR_dmesg
@@ -904,9 +905,9 @@
#undef FLAG_t
#endif
-// grep C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw] C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]
+// grep S(exclude)*M(include)*C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw] S(exclude)*M(include)*C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]
#undef OPTSTR_grep
-#define OPTSTR_grep "C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]"
+#define OPTSTR_grep "S(exclude)*M(include)*C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]"
#ifdef CLEANUP_grep
#undef CLEANUP_grep
#undef FOR_grep
@@ -935,6 +936,10 @@
#undef FLAG_A
#undef FLAG_B
#undef FLAG_C
+#undef FLAG_include
+#undef FLAG_M
+#undef FLAG_exclude
+#undef FLAG_S
#endif
// groupadd <1>2g#<0S
@@ -3522,7 +3527,8 @@
#define FLAG_u (1<<7)
#define FLAG_d (1<<8)
#define FLAG_m (1<<9)
-#define FLAG_no_preserve_owner (1<<10)
+#define FLAG_trailer (1<<10)
+#define FLAG_no_preserve_owner (1<<11)
#endif
#ifdef FOR_crond
@@ -4002,6 +4008,10 @@
#define FLAG_A (1<<22)
#define FLAG_B (1<<23)
#define FLAG_C (1<<24)
+#define FLAG_include (1<<25)
+#define FLAG_M (1<<25)
+#define FLAG_exclude (1<<26)
+#define FLAG_S (1<<26)
#endif
#ifdef FOR_groupadd
diff --git a/generated/globals.h b/generated/globals.h
index d183b1f9..00fcc16c 100644
--- a/generated/globals.h
+++ b/generated/globals.h
@@ -39,6 +39,16 @@ struct skeleton_data {
int more_globals;
};
+// toys/lsb/dmesg.c
+
+struct dmesg_data {
+ long level;
+ long size;
+
+ int use_color;
+ time_t tea;
+};
+
// toys/lsb/hostname.c
struct hostname_data {
@@ -549,16 +559,6 @@ struct diff_data {
int *offset[2];
};
-// toys/pending/dmesg.c
-
-struct dmesg_data {
- long level;
- long size;
-
- int use_color;
- struct sysinfo info;
-};
-
// toys/pending/dumpleases.c
struct dumpleases_data {
@@ -1107,8 +1107,11 @@ struct grep_data {
long a;
long b;
long c;
+ struct arg_list *M;
+ struct arg_list *S;
char indelim, outdelim;
+ int found;
};
// toys/posix/head.c
@@ -1393,6 +1396,7 @@ extern union global_union {
struct log_data log;
struct hello_data hello;
struct skeleton_data skeleton;
+ struct dmesg_data dmesg;
struct hostname_data hostname;
struct killall_data killall;
struct md5sum_data md5sum;
@@ -1449,7 +1453,6 @@ extern union global_union {
struct dhcp6_data dhcp6;
struct dhcpd_data dhcpd;
struct diff_data diff;
- struct dmesg_data dmesg;
struct dumpleases_data dumpleases;
struct expr_data expr;
struct fdisk_data fdisk;
diff --git a/generated/help.h b/generated/help.h
index 28582a26..49a14f95 100644
--- a/generated/help.h
+++ b/generated/help.h
@@ -108,6 +108,8 @@
#define HELP_hostname "usage: hostname [-b] [-F FILENAME] [newname]\n\nGet/Set the current hostname\n\n-b Set hostname to 'localhost' if otherwise unset\n-F Set hostname to contents of FILENAME\n\n"
+#define HELP_dmesg "usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]\n\nPrint or control the kernel ring buffer.\n\n-C Clear ring buffer without printing\n-c Clear ring buffer after printing\n-n Set kernel logging LEVEL (1-9)\n-r Raw output (with <level markers>)\n-S Use syslog(2) rather than /dev/kmsg\n-s Show the last SIZE many bytes\n-T Show human-readable timestamps\n-t Don't print timestamps\n-w Keep waiting for more output (aka --follow)\n\n"
+
#define HELP_tunctl "usage: tunctl [-dtT] [-u USER] NAME\n\nCreate and delete tun/tap virtual ethernet devices.\n\n-T Use tap (ethernet frames) instead of tun (ip packets)\n-d Delete tun/tap device\n-t Create tun/tap device\n-u Set owner (user who can read/write device without root access)\n\n\n"
#define HELP_rfkill "Usage: rfkill COMMAND [DEVICE]\n\nEnable/disable wireless devices.\n\nCommands:\nlist [DEVICE] List current state\nblock DEVICE Disable device\nunblock DEVICE Enable device\n\nDEVICE is an index number, or one of:\nall, wlan(wifi), bluetooth, uwb(ultrawideband), wimax, wwan, gps, fm.\n\n"
@@ -398,8 +400,6 @@
#define HELP_dumpleases "usage: dumpleases [-r|-a] [-f LEASEFILE]\n\nDisplay DHCP leases granted by udhcpd\n-f FILE, Lease file\n-r Show remaining time\n-a Show expiration time\n\n"
-#define HELP_dmesg "usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]\n\nPrint or control the kernel ring buffer.\n\n-C Clear ring buffer without printing\n-c Clear ring buffer after printing\n-n Set kernel logging LEVEL (1-9)\n-r Raw output (with <level markers>)\n-S Use syslog(2) rather than /dev/kmsg\n-s Show the last SIZE many bytes\n-T Show human-readable timestamps\n-t Don't print timestamps\n-w Keep waiting for more output (aka --follow)\n\n"
-
#define HELP_diff "usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2\n\n-a Treat all files as text\n-b Ignore changes in the amount of whitespace\n-B Ignore changes whose lines are all blank\n-d Try hard to find a smaller set of changes\n-i Ignore case differences\n-L Use LABEL instead of the filename in the unified header\n-N Treat absent files as empty\n-q Output only whether files differ\n-r Recurse\n-S Start with FILE when comparing directories\n-T Make tabs line up by prefixing a tab when necessary\n-s Report when two files are the same\n-t Expand tabs to spaces in output\n-U Output LINES lines of context\n-w Ignore all whitespace\n\n"
#define HELP_dhcpd "usage: dhcpd [-46fS] [-i IFACE] [-P N] [CONFFILE]\n\n -f Run in foreground\n -i Interface to use\n -S Log to syslog too\n -P N Use port N (default ipv4 67, ipv6 547)\n -4, -6 Run as a DHCPv4 or DHCPv6 server\n\n"
@@ -480,17 +480,13 @@
#define HELP_pwd "usage: pwd [-L|-P]\n\nPrint working (current) directory.\n\n-L Use shell's path from $PWD (when applicable)\n-P Print cannonical absolute path\n\n"
-#define HELP_pgkill_common "usage: * [-fnovx] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,] [-t TERM,] [-U UID,] [-u EUID,]\n\n-f Check full command line for PATTERN\n-G Match real Group ID(s)\n-g Match Process Group(s) (0 is current user)\n-n Newest match only\n-o Oldest match only\n-P Match Parent Process ID(s)\n-s Match Session ID(s) (0 for current)\n-t Match Terminal(s)\n-U Match real User ID(s)\n-u Match effective User ID(s)\n-v Negate the match\n-x Match whole command (not substring)\n\n"
-
-#define HELP_pkill "usage: pkill [-SIGNAL|-l SIGNAL] [PATTERN]\n\n-l Send SIGNAL (default SIGTERM)\n-V verbose\n\n"
-
-#define HELP_pgrep "usage: pgrep [-cl] [-d DELIM] [-L SIGNAL] [PATTERN]\n\nSearch for process(es). PATTERN is an extended regular expression checked\nagainst command names.\n\n-c Show only count of matches\n-d Use DELIM instead of newline\n-L Send SIGNAL instead of printing name\n-l Show command name\n\n"
+#define HELP_pkill "usage: pkill [-fnovx] [-SIGNAL|-l SIGNAL] [PATTERN] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,] [-t TERM,] [-U UID,] [-u EUID,]\n\n-l Send SIGNAL (default SIGTERM)\n-V verbose\n-f Check full command line for PATTERN\n-G Match real Group ID(s)\n-g Match Process Group(s) (0 is current user)\n-n Newest match only\n-o Oldest match only\n-P Match Parent Process ID(s)\n-s Match Session ID(s) (0 for current)\n-t Match Terminal(s)\n-U Match real User ID(s)\n-u Match effective User ID(s)\n-v Negate the match\n-x Match whole command (not substring)\n\n"
-#define HELP_top_common "usage: * [-bq] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]\n\n-b Batch mode (no tty)\n-d Delay SECONDS between each cycle (default 3)\n-n Exit after NUMBER iterations\n-p Show these PIDs\n-u Show these USERs\n-q Quiet (no header lines)\n\nCursor LEFT/RIGHT to change sort, UP/DOWN move list, space to force\nupdate, R to reverse sort, Q to exit.\n\n"
+#define HELP_pgrep "usage: pgrep [-clfnovx] [-d DELIM] [-L SIGNAL] [PATTERN] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,] [-t TERM,] [-U UID,] [-u EUID,]\n\nSearch for process(es). PATTERN is an extended regular expression checked\nagainst command names.\n\n-c Show only count of matches\n-d Use DELIM instead of newline\n-L Send SIGNAL instead of printing name\n-l Show command name\n-f Check full command line for PATTERN\n-G Match real Group ID(s)\n-g Match Process Group(s) (0 is current user)\n-n Newest match only\n-o Oldest match only\n-P Match Parent Process ID(s)\n-s Match Session ID(s) (0 for current)\n-t Match Terminal(s)\n-U Match real User ID(s)\n-u Match effective User ID(s)\n-v Negate the match\n-x Match whole command (not substring)\n\n"
-#define HELP_iotop "usage: iotop [-AaKO]\n\nRank processes by I/O.\n\n-A All I/O, not just disk\n-a Accumulated I/O (not percentage)\n-K Kilobytes\n-k Fallback sort FIELDS (default -[D]IO,-ETIME,-PID)\n-O Only show processes doing I/O\n-o Show FIELDS (default PID,PR,USER,[D]READ,[D]WRITE,SWAP,[D]IO,COMM)\n-s Sort by field number (0-X, default 6)\n\n"
+#define HELP_iotop "usage: iotop [-AaKObq] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]\n\nRank processes by I/O.\n\n-A All I/O, not just disk\n-a Accumulated I/O (not percentage)\n-K Kilobytes\n-k Fallback sort FIELDS (default -[D]IO,-ETIME,-PID)\n-O Only show processes doing I/O\n-o Show FIELDS (default PID,PR,USER,[D]READ,[D]WRITE,SWAP,[D]IO,COMM)\n-s Sort by field number (0-X, default 6)\n-b Batch mode (no tty)\n-d Delay SECONDS between each cycle (default 3)\n-n Exit after NUMBER iterations\n-p Show these PIDs\n-u Show these USERs\n-q Quiet (no header lines)\n\nCursor LEFT/RIGHT to change sort, UP/DOWN move list, space to force\nupdate, R to reverse sort, Q to exit.\n\n"
-#define HELP_top "usage: top [-H] [-k FIELD,] [-o FIELD,] [-s SORT]\n\nShow process activity in real time.\n\n-H Show threads\n-k Fallback sort FIELDS (default -S,-%CPU,-ETIME,-PID)\n-o Show FIELDS (def PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,CMDLINE)\n-O Add FIELDS (replacing PR,NI,VIRT,RES,SHR,S from default)\n-s Sort by field number (1-X, default 9)\n\n"
+#define HELP_top "usage: top [-Hbq] [-k FIELD,] [-o FIELD,] [-s SORT] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]\n\nShow process activity in real time.\n\n-H Show threads\n-k Fallback sort FIELDS (default -S,-%CPU,-ETIME,-PID)\n-o Show FIELDS (def PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,CMDLINE)\n-O Add FIELDS (replacing PR,NI,VIRT,RES,SHR,S from default)\n-s Sort by field number (1-X, default 9)\n-b Batch mode (no tty)\n-d Delay SECONDS between each cycle (default 3)\n-n Exit after NUMBER iterations\n-p Show these PIDs\n-u Show these USERs\n-q Quiet (no header lines)\n\nCursor LEFT/RIGHT to change sort, UP/DOWN move list, space to force\nupdate, R to reverse sort, Q to exit.\n\n"
#define HELP_ps "usage: ps [-AadefLlnwZ] [-gG GROUP,] [-k FIELD,] [-o FIELD,] [-p PID,] [-t TTY,] [-uU USER,]\n\nList processes.\n\nWhich processes to show (selections may be comma separated lists):\n\n-A All processes\n-a Processes with terminals that aren't session leaders\n-d All processes that aren't session leaders\n-e Same as -A\n-g Belonging to GROUPs\n-G Belonging to real GROUPs (before sgid)\n-p PIDs (--pid)\n-P Parent PIDs (--ppid)\n-s In session IDs\n-t Attached to selected TTYs\n-T Show threads\n-u Owned by USERs\n-U Owned by real USERs (before suid)\n\nOutput modifiers:\n\n-k Sort FIELDs in +increasing or -decreasting order (--sort)\n-M Measure field widths (expanding as necessary)\n-n Show numeric USER and GROUP\n-w Wide output (don't truncate fields)\n\nWhich FIELDs to show. (Default = -o PID,TTY,TIME,CMD)\n\n-f Full listing (-o USER:12=UID,PID,PPID,C,STIME,TTY,TIME,ARGS=CMD)\n-l Long listing (-o F,S,UID,PID,PPID,C,PRI,NI,ADDR,SZ,WCHAN,TTY,TIME,CMD)\n-o Output FIELDs instead of defaults, each with optional :size and =title\n-O Add FIELDS to defaults\n-Z Include LABEL\n\nCommand line -o fields:\n\n ARGS CMDLINE minus initial path CMD Command (thread) name (stat[2])\n CMDLINE Command line (argv[]) COMM Command filename (/proc/$PID/exe)\n COMMAND Command file (/proc/$PID/exe) NAME Process name (argv[0] of $PID)\n\nProcess attribute -o FIELDs:\n\n ADDR Instruction pointer BIT Is this process 32 or 64 bits\n CPU Which processor running on ETIME Elapsed time since PID start\n F Flags (1=FORKNOEXEC 4=SUPERPRIV) GID Group id\n GROUP Group name LABEL Security label\n MAJFL Major page faults MINFL Minor page faults\n NI Niceness (lower is faster)\n PCPU Percentage of CPU time used PCY Android scheduling policy\n PGID Process Group ID\n PID Process ID PPID Parent Process ID\n PRI Priority (higher is faster) PSR Processor last executed on\n RGID Real (before sgid) group ID RGROUP Real (before sgid) group name\n RSS Resident Set Size (pages in use) RTPRIO Realtime priority\n RUID Real (before suid) user ID RUSER Real (before suid) user name\n S Process state:\n R (running) S (sleeping) D (device I/O) T (stopped) t (traced)\n Z (zombie) X (deader) x (dead) K (wakekill) W (waking)\n SCHED Scheduling policy (0=other, 1=fifo, 2=rr, 3=batch, 4=iso, 5=idle)\n STAT Process state (S) plus:\n < high priority N low priority L locked memory\n s session leader + foreground l multithreaded\n STIME Start time of process in hh:mm (size :19 shows yyyy-mm-dd hh:mm:ss)\n SZ Memory Size (4k pages needed to completely swap out process)\n TCNT Thread count TID Thread ID\n TIME CPU time consumed TTY Controlling terminal\n UID User id USER User name\n VSZ Virtual memory size (1k units) %VSZ VSZ as % of physical memory\n WCHAN What are we waiting in kernel for\n\n"
@@ -536,7 +532,7 @@
#define HELP_head "usage: head [-n number] [file...]\n\nCopy first lines from files to stdout. If no files listed, copy from\nstdin. Filename \"-\" is a synonym for stdin.\n\n-n Number of lines to copy\n-q Never print headers\n-v Always print headers\n\n"
-#define HELP_grep "usage: grep [-EFivwcloqsHbhn] [-A NUM] [-m MAX] [-e REGEX]... [-f REGFILE] [FILE]...\n\nShow lines matching regular expressions. If no -e, first argument is\nregular expression to match. With no files (or \"-\" filename) read stdin.\nReturns 0 if matched, 1 if no match found.\n\n-e Regex to match. (May be repeated.)\n-f File containing regular expressions to match.\n\nmatch type:\n-A Show NUM lines after -B Show NUM lines before match\n-C NUM lines context (A+B) -E extended regex syntax\n-F fixed (literal match) -i case insensitive\n-m match MAX many lines -r recursive (on dir)\n-v invert match -w whole word (implies -E)\n-x whole line -z input NUL terminated\n\ndisplay modes: (default: matched line)\n-c count of matching lines -l show matching filenames\n-o only matching part -q quiet (errors only)\n-s silent (no error msg) -Z output NUL terminated\n\noutput prefix (default: filename if checking more than 1 file)\n-H force filename -b byte offset of match\n-h hide filename -n line number of match\n\n"
+#define HELP_grep "usage: grep [-EFrivwcloqsHbhn] [-ABC NUM] [-m MAX] [-e REGEX]... [-MS PATTERN]... [-f REGFILE] [FILE]...\n\nShow lines matching regular expressions. If no -e, first argument is\nregular expression to match. With no files (or \"-\" filename) read stdin.\nReturns 0 if matched, 1 if no match found.\n\n-e Regex to match. (May be repeated.)\n-f File listing regular expressions to match.\n\nfile search:\n-r Recurse into subdirectories (defaults FILE to \".\")\n-M Match filename pattern (--include)\n-S Skip filename pattern (--exclude)\n\nmatch type:\n-A Show NUM lines after -B Show NUM lines before match\n-C NUM lines context (A+B) -E extended regex syntax\n-F fixed (literal match) -i case insensitive\n-m match MAX many lines -v invert match\n-w whole word (implies -E) -x whole line\n-z input NUL terminated\n\ndisplay modes: (default: matched line)\n-c count of matching lines -l show matching filenames\n-o only matching part -q quiet (errors only)\n-s silent (no error msg) -Z output NUL terminated\n\noutput prefix (default: filename if checking more than 1 file)\n-H force filename -b byte offset of match\n-h hide filename -n line number of match\n\n"
#define HELP_find "usage: find [-HL] [DIR...] [<options>]\n\nSearch directories for matching files.\nDefault: search \".\" match all -print all matches.\n\n-H Follow command line symlinks -L Follow all symlinks\n\nMatch filters:\n-name PATTERN filename with wildcards -iname case insensitive -name\n-path PATTERN path name with wildcards -ipath case insensitive -path\n-user UNAME belongs to user UNAME -nouser user ID not known\n-group GROUP belongs to group GROUP -nogroup group ID not known\n-perm [-/]MODE permissions (-=min /=any) -prune ignore contents of dir\n-size N[c] 512 byte blocks (c=bytes) -xdev only this filesystem\n-links N hardlink count -atime N[u] accessed N units ago\n-ctime N[u] created N units ago -mtime N[u] modified N units ago\n-newer FILE newer mtime than FILE -mindepth # at least # dirs down\n-depth ignore contents of dir -maxdepth # at most # dirs down\n-inum N inode number N -empty empty files and dirs\n-type [bcdflps] (block, char, dir, file, symlink, pipe, socket)\n\nNumbers N may be prefixed by a - (less than) or + (greater than). Units for\n-Xtime are d (days, default), h (hours), m (minutes), or s (seconds).\n\nCombine matches with:\n!, -a, -o, ( ) not, and, or, group expressions\n\nActions:\n-print Print match with newline -print0 Print match with null\n-exec Run command with path -execdir Run command in file's dir\n-ok Ask before exec -okdir Ask before execdir\n-delete Remove matching file/dir\n\nCommands substitute \"{}\" with matched file. End with \";\" to run each file,\nor \"+\" (next argument after \"{}\") to collect and run with multiple files.\n\n"
@@ -560,7 +556,7 @@
#define HELP_cut "usage: cut OPTION... [FILE]...\n\nPrint selected parts of lines from each FILE to standard output.\n\n-b LIST select only these bytes from LIST\n-c LIST select only these characters from LIST\n-f LIST select only these fields\n-d DELIM use DELIM instead of TAB for field delimiter\n-s do not print lines not containing delimiters\n-n don't split multibyte characters (ignored)\n\n"
-#define HELP_cpio "usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner]\n [ignored: -mdu -H newc]\n\ncopy files into and out of a \"newc\" format cpio archive\n\n-F FILE use archive FILE instead of stdin/stdout\n-p DEST copy-pass mode, copy stdin file list to directory DEST\n-i extract from archive into file system (stdin=archive)\n-o create archive (stdin=list of files, stdout=archive)\n-t test files (list only, stdin=archive, stdout=list of files)\n-v verbose (list files during create/extract)\n--no-preserve-owner (don't set ownership during extract)\n\n"
+#define HELP_cpio "usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner]\n [ignored: -mdu -H newc]\n\ncopy files into and out of a \"newc\" format cpio archive\n\n-F FILE use archive FILE instead of stdin/stdout\n-p DEST copy-pass mode, copy stdin file list to directory DEST\n-i extract from archive into file system (stdin=archive)\n-o create archive (stdin=list of files, stdout=archive)\n-t test files (list only, stdin=archive, stdout=list of files)\n-v verbose (list files during create/extract)\n--no-preserve-owner (don't set ownership during extract)\n--trailer Add legacy trailer (prevents concatenation).\n\n"
#define HELP_install "usage: install [-dDpsv] [-o USER] [-g GROUP] [-m MODE] [SOURCE...] DEST\n\nCopy files and set attributes.\n\n-d Act like mkdir -p\n-D Create leading directories for DEST\n-g Make copy belong to GROUP\n-m Set permissions to MODE\n-o Make copy belong to USER\n-p Preserve timestamps\n-s Call \"strip -p\"\n-v Verbose\n\n"
diff --git a/generated/newtoys.h b/generated/newtoys.h
index d55ca13f..fc2811dc 100644
--- a/generated/newtoys.h
+++ b/generated/newtoys.h
@@ -35,7 +35,7 @@ USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
USE_COMPRESS(NEWTOY(compress, "zcd9lrg[-cd][!zgLr]", TOYFLAG_USR|TOYFLAG_BIN))
USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
USE_CP(NEWTOY(cp, "<2"USE_CP_PRESERVE("(preserve):;")"RHLPprdaslvnF(remove-destination)fi[-HLPd][-ni]", TOYFLAG_BIN))
-USE_CPIO(NEWTOY(cpio, "(no-preserve-owner)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
+USE_CPIO(NEWTOY(cpio, "(no-preserve-owner)(trailer)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
USE_CRONTAB(NEWTOY(crontab, "c:u:elr[!elr]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
USE_CUT(NEWTOY(cut, "b:|c:|f:|d:sn[!cbf]", TOYFLAG_USR|TOYFLAG_BIN))
@@ -50,7 +50,7 @@ USE_DHCP6(NEWTOY(dhcp6, "r:A#<0T#<0t#<0s:p:i:SRvqnbf", TOYFLAG_SBIN|TOYFLAG_ROOT
USE_DHCPD(NEWTOY(dhcpd, ">1P#<0>65535fi:S46[!46]", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
USE_DIFF(NEWTOY(diff, "<2>2B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN))
USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN))
-USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc]", TOYFLAG_BIN))
+USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]", TOYFLAG_BIN))
USE_DOS2UNIX(NEWTOY(dos2unix, 0, TOYFLAG_BIN))
USE_DU(NEWTOY(du, "d#<0hmlcaHkKLsx[-HL][-kKmh]", TOYFLAG_USR|TOYFLAG_BIN))
USE_DUMPLEASES(NEWTOY(dumpleases, ">0arf:[!ar]", TOYFLAG_USR|TOYFLAG_BIN))
@@ -82,7 +82,7 @@ USE_GETENFORCE(NEWTOY(getenforce, ">0", TOYFLAG_USR|TOYFLAG_SBIN))
USE_GETFATTR(NEWTOY(getfattr, "dhn:", TOYFLAG_USR|TOYFLAG_BIN))
USE_GETPROP(NEWTOY(getprop, ">2Z", TOYFLAG_USR|TOYFLAG_SBIN))
USE_GETTY(NEWTOY(getty, "<2t#<0H:I:l:f:iwnmLh",TOYFLAG_SBIN))
-USE_GREP(NEWTOY(grep, "C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]", TOYFLAG_BIN))
+USE_GREP(NEWTOY(grep, "S(exclude)*M(include)*C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]", TOYFLAG_BIN))
USE_GROUPADD(NEWTOY(groupadd, "<1>2g#<0S", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
USE_GROUPDEL(NEWTOY(groupdel, "<1>2", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
USE_GROUPS(NEWTOY(groups, NULL, TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/lib/args.c b/lib/args.c
index 20084f36..00932de9 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -136,7 +136,7 @@ static int gotflag(struct getoptflagstate *gof, struct opts *opt)
// Did we recognize this option?
if (!opt) {
if (gof->noerror) return 1;
- error_exit("Unknown option %s", gof->arg);
+ help_exit("Unknown option %s", gof->arg);
}
// Might enabling this switch off something else?
@@ -163,7 +163,7 @@ static int gotflag(struct getoptflagstate *gof, struct opts *opt)
if (opt == bad || !(i & toys.optflags)) continue;
if (toys.optflags & bad->dex[2]) break;
}
- if (bad) error_exit("No '%c' with '%c'", opt->c, bad->c);
+ if (bad) help_exit("No '%c' with '%c'", opt->c, bad->c);
}
// Does this option take an argument?
@@ -187,10 +187,10 @@ static int gotflag(struct getoptflagstate *gof, struct opts *opt)
char *s = "Missing argument to ";
struct longopts *lo;
- if (opt->c != -1) error_exit("%s-%c", s, opt->c);
+ if (opt->c != -1) help_exit("%s-%c", s, opt->c);
for (lo = gof->longopts; lo->opt != opt; lo = lo->next);
- error_exit("%s--%.*s", s, lo->len, lo->str);
+ help_exit("%s--%.*s", s, lo->len, lo->str);
}
if (type == ':') *(opt->arg) = (long)arg;
@@ -204,8 +204,8 @@ static int gotflag(struct getoptflagstate *gof, struct opts *opt)
} else if (type == '#' || type == '-') {
long l = atolx(arg);
if (type == '-' && !ispunct(*arg)) l*=-1;
- if (l < opt->val[0].l) error_exit("-%c < %ld", opt->c, opt->val[0].l);
- if (l > opt->val[1].l) error_exit("-%c > %ld", opt->c, opt->val[1].l);
+ if (l < opt->val[0].l) help_exit("-%c < %ld", opt->c, opt->val[0].l);
+ if (l > opt->val[1].l) help_exit("-%c > %ld", opt->c, opt->val[1].l);
*(opt->arg) = l;
} else if (CFG_TOYBOX_FLOAT && type == '.') {
@@ -213,9 +213,9 @@ static int gotflag(struct getoptflagstate *gof, struct opts *opt)
*f = strtod(arg, &arg);
if (opt->val[0].l != LONG_MIN && *f < opt->val[0].f)
- error_exit("-%c < %lf", opt->c, (double)opt->val[0].f);
+ help_exit("-%c < %lf", opt->c, (double)opt->val[0].f);
if (opt->val[1].l != LONG_MAX && *f > opt->val[1].f)
- error_exit("-%c > %lf", opt->c, (double)opt->val[1].f);
+ help_exit("-%c > %lf", opt->c, (double)opt->val[1].f);
}
if (!gof->nodash_now) gof->arg = "";
@@ -475,10 +475,10 @@ notflag:
// Sanity check
if (toys.optc<gof.minargs)
- error_exit("Need%s %d argument%s", letters[!!(gof.minargs-1)],
+ help_exit("Need%s %d argument%s", letters[!!(gof.minargs-1)],
gof.minargs, letters[!(gof.minargs-1)]);
if (toys.optc>gof.maxargs)
- error_exit("Max %d argument%s", gof.maxargs, letters[!(gof.maxargs-1)]);
+ help_exit("Max %d argument%s", gof.maxargs, letters[!(gof.maxargs-1)]);
if (gof.requires && !(gof.requires & toys.optflags)) {
struct opts *req;
char needs[32], *s = needs;
@@ -487,7 +487,7 @@ notflag:
if (req->flags & 1) *(s++) = req->c;
*s = 0;
- error_exit("Needs %s-%s", s[1] ? "one of " : "", needs);
+ help_exit("Needs %s-%s", s[1] ? "one of " : "", needs);
}
if (CFG_TOYBOX_FREE) {
diff --git a/lib/lib.c b/lib/lib.c
index b6277f3b..ceb1bc7d 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -66,7 +66,8 @@ void help_exit(char *msg, ...)
{
va_list va;
- if (CFG_TOYBOX_HELP) show_help(stderr);
+ if (CFG_TOYBOX_HELP)
+ fprintf(stderr, "See %s --help\n", toys.which->name);
if (msg) {
va_start(va, msg);
@@ -392,6 +393,8 @@ int unescape(char c)
return (idx == -1) ? 0 : to[idx];
}
+// If string ends with suffix return pointer to start of suffix in string,
+// else NULL
char *strend(char *str, char *suffix)
{
long a = strlen(str), b = strlen(suffix);
diff --git a/lib/portability.h b/lib/portability.h
index e62de139..e3e0ef04 100644
--- a/lib/portability.h
+++ b/lib/portability.h
@@ -240,7 +240,7 @@ pid_t xfork(void);
//#define strncpy(...) @@strncpyisbadmmkay@@
//#define strncat(...) @@strncatisbadmmkay@@
-#if CFG_TOYBOX_ANDROID_SCHEDPOLICY
+#if CFG_TOYBOX_ANDROID_SCHEDPOLICY && defined(__BIONIC__)
#include <cutils/sched_policy.h>
#else
static inline int get_sched_policy(int tid, void *policy) {return 0;}
diff --git a/scripts/config2help.c b/scripts/config2help.c
index 6ec5e841..575b7b8a 100644
--- a/scripts/config2help.c
+++ b/scripts/config2help.c
@@ -1,4 +1,9 @@
-//#include "toys.h"
+/* config2.help.c - config2hep Config.in .config > help.h
+
+ function parse() reads Config.in data into *sym list, then
+ we read .config and set sym->try on each enabled symbol.
+
+*/
#include <ctype.h>
#include <stdio.h>
@@ -12,6 +17,7 @@
#include <termios.h>
#include <poll.h>
#include <sys/socket.h>
+
struct statvfs {int i;};
#include "lib/portability.h"
#include "lib/lib.h"
@@ -32,7 +38,7 @@ struct symbol {
} *sym;
// remove leading spaces
-char *trim(char *s)
+char *skip_spaces(char *s)
{
while (isspace(*s)) s++;
@@ -44,11 +50,11 @@ char *keyword(char *name, char *line)
{
int len = strlen(name);
- line = trim(line);
+ line = skip_spaces(line);
if (strncmp(name, line, len)) return 0;
line += len;
if (*line && !isspace(*line)) return 0;
- line = trim(line);
+ line = skip_spaces(line);
return line;
}
@@ -71,7 +77,7 @@ int zap_blank_lines(struct double_list **help)
while (*help) {
char *s;
- s = trim((*help)->data);
+ s = skip_spaces((*help)->data);
if (*s) break;
got++;
@@ -104,7 +110,7 @@ char **grab_dashlines(struct double_list **help, struct double_list **from,
// Find start of dash block. Must be at start or after blank line.
for (;;) {
- s = trim((*from)->data);
+ s = skip_spaces((*from)->data);
if (*s == '-' && s[1] != '-' && !count) break;
if (!*s) count = 0;
@@ -117,7 +123,7 @@ char **grab_dashlines(struct double_list **help, struct double_list **from,
// If there was whitespace before this, zap it. This can't take out *help
// because zap_blank_lines skipped blank lines, and we had to have at least
// one non-blank line (a dash line) to get this far.
- while (!*trim((*from)->prev->data)) {
+ while (!*skip_spaces((*from)->prev->data)) {
*from = (*from)->prev;
free(dlist_zap(from));
}
@@ -128,7 +134,7 @@ char **grab_dashlines(struct double_list **help, struct double_list **from,
dd = *from;
if (*help == *from) *help = 0;
for (;;) {
- if (*trim(dd->data) != '-') break;
+ if (*skip_spaces(dd->data) != '-') break;
count++;
if (*from == (dd = dd->next)) break;
}
@@ -140,6 +146,7 @@ char **grab_dashlines(struct double_list **help, struct double_list **from,
return list;
}
+// Read Config.in (and includes) to populate global struct symbol *sym list.
void parse(char *filename)
{
FILE *fp = xfopen(filename, "r");
@@ -208,6 +215,8 @@ int dashlinesort(char **a, char **b)
return strcmp(*a, *b);
}
+// Three stages: read data, collate entries, output results.
+
int main(int argc, char *argv[])
{
FILE *fp;
@@ -217,6 +226,9 @@ int main(int argc, char *argv[])
exit(1);
}
+ // Stage 1: read data. Read Config.in to global 'struct symbol *sym' list,
+ // then read .config to set "enabled" member of each enabled symbol.
+
// Read Config.in
parse(argv[1]);
@@ -241,6 +253,8 @@ int main(int argc, char *argv[])
}
}
+ // Stage 2: process data.
+
// Collate help according to usage, depends, and .config
// Loop through each entry, finding duplicate enabled "usage:" names
@@ -266,7 +280,7 @@ int main(int argc, char *argv[])
catch->enabled++;
while (!isspace(*that) && *that) that++;
if (!throw) len = that-name;
- that = trim(that);
+ that = skip_spaces(that);
if (!throw) {
throw = catch;
this = that;
@@ -305,7 +319,7 @@ int main(int argc, char *argv[])
}
while (throw->help && throw->help != tfrom)
dlist_add(&cfrom, dlist_zap(&throw->help));
- if (cfrom && cfrom->prev->data && *trim(cfrom->prev->data))
+ if (cfrom && cfrom->prev->data && *skip_spaces(cfrom->prev->data))
dlist_add(&cfrom, strdup(""));
}
if (!anchor) {
@@ -326,7 +340,7 @@ int main(int argc, char *argv[])
if (!anchor->data) dlist_zap(&anchor);
// zap whitespace at end of catch help text
- while (!*trim(anchor->prev->data)) {
+ while (!*skip_spaces(anchor->prev->data)) {
anchor = anchor->prev;
free(dlist_zap(&anchor));
}
@@ -345,8 +359,8 @@ int main(int argc, char *argv[])
if (from[ff] == ']' && to[tt] == ']') {
try = xmprintf("[-%.*s%.*s] ", ff, from, tt, to);
qsort(try+2, ff+tt, 1, (void *)charsort);
- this = trim(this+ff+3);
- that = trim(that+tt+3);
+ this = skip_spaces(this+ff+3);
+ that = skip_spaces(that+tt+3);
}
}
@@ -375,6 +389,8 @@ int main(int argc, char *argv[])
if (!throw) break;
}
+ // Stage 3: output results to stdout.
+
// Print out help #defines
while (sym) {
struct double_list *dd;
diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c
new file mode 100644
index 00000000..30f90e3a
--- /dev/null
+++ b/toys/lsb/dmesg.c
@@ -0,0 +1,182 @@
+/* dmesg.c - display/control kernel ring buffer.
+ *
+ * Copyright 2006, 2007 Rob Landley <rob@landley.net>
+ *
+ * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/dmesg.html
+ *
+ * Don't ask me why the horrible new dmesg API is still in "testing":
+ * http://kernel.org/doc/Documentation/ABI/testing/dev-kmsg
+
+// We care that FLAG_c is 1, so keep c at the end.
+USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]", TOYFLAG_BIN))
+
+config DMESG
+ bool "dmesg"
+ default y
+ help
+ usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]
+
+ Print or control the kernel ring buffer.
+
+ -C Clear ring buffer without printing
+ -c Clear ring buffer after printing
+ -n Set kernel logging LEVEL (1-9)
+ -r Raw output (with <level markers>)
+ -S Use syslog(2) rather than /dev/kmsg
+ -s Show the last SIZE many bytes
+ -T Show human-readable timestamps
+ -t Don't print timestamps
+ -w Keep waiting for more output (aka --follow)
+*/
+
+#define FOR_dmesg
+#include "toys.h"
+#include <sys/klog.h>
+
+GLOBALS(
+ long level;
+ long size;
+
+ int use_color;
+ time_t tea;
+)
+
+static void color(int c)
+{
+ if (TT.use_color) printf("\033[%dm", c);
+}
+
+static void format_message(char *msg, int new)
+{
+ unsigned long long time_s, time_us;
+ int facpri, subsystem, pos;
+ char *p, *text;
+
+ // The new /dev/kmsg and the old syslog(2) formats differ slightly.
+ if (new) {
+ if (sscanf(msg, "%u,%*u,%llu,%*[^;]; %n", &facpri, &time_us, &pos) != 2)
+ return;
+
+ time_s = time_us/1000000;
+ time_us %= 1000000;
+ } else if (sscanf(msg, "<%u>[%llu.%llu] %n",
+ &facpri, &time_s, &time_us, &pos) != 3) return;
+
+ // Drop extras after end of message text.
+ if ((p = strchr(text = msg+pos, '\n'))) *p = 0;
+
+ // Is there a subsystem? (The ": " is just a convention.)
+ p = strstr(text, ": ");
+ subsystem = p ? (p-text) : 0;
+
+ // To get "raw" output for /dev/kmsg we need to add priority to each line
+ if (toys.optflags&FLAG_r) {
+ color(0);
+ printf("<%d>", facpri);
+ }
+
+ // Format the time.
+ if (!(toys.optflags&FLAG_t)) {
+ color(32);
+ if (toys.optflags&FLAG_T) {
+ time_t t = TT.tea+time_s;
+ char *ts = ctime(&t);
+
+ printf("[%.*s] ", (int)(strlen(ts)-1), ts);
+ } else printf("[%5lld.%06lld] ", time_s, time_us);
+ }
+
+ // Errors (or worse) are shown in red, subsystems are shown in yellow.
+ if (subsystem) {
+ color(33);
+ printf("%.*s", subsystem, text);
+ text += subsystem;
+ }
+ color(31*((facpri&7)<=3));
+ xputs(text);
+}
+
+static int xklogctl(int type, char *buf, int len)
+{
+ int rc = klogctl(type, buf, len);
+
+ if (rc<0) perror_exit("klogctl");
+
+ return rc;
+}
+
+static void dmesg_cleanup(void)
+{
+ color(0);
+}
+
+void dmesg_main(void)
+{
+ TT.use_color = isatty(1);
+
+ if (TT.use_color) sigatexit(dmesg_cleanup);
+ // If we're displaying output, is it klogctl or /dev/kmsg?
+ if (toys.optflags & (FLAG_C|FLAG_n)) goto no_output;
+
+ if (toys.optflags&FLAG_T) {
+ struct sysinfo info;
+
+ sysinfo(&info);
+ TT.tea = time(0)-info.uptime;
+ }
+
+ if (!(toys.optflags&FLAG_S)) {
+ char msg[8193]; // CONSOLE_EXT_LOG_MAX+1
+ ssize_t len;
+ int fd;
+
+ // Each read returns one message. By default, we block when there are no
+ // more messages (--follow); O_NONBLOCK is needed for for usual behavior.
+ fd = open("/dev/kmsg", O_RDONLY|(O_NONBLOCK*!(toys.optflags&FLAG_w)));
+ if (fd == -1) goto klogctl_mode;
+
+ // SYSLOG_ACTION_CLEAR(5) doesn't actually remove anything from /dev/kmsg,
+ // you need to seek to the last clear point.
+ lseek(fd, 0, SEEK_DATA);
+
+ for (;;) {
+ // why does /dev/kmesg return EPIPE instead of EAGAIN if oldest message
+ // expires as we read it?
+ if (-1==(len = read(fd, msg, sizeof(msg))) && errno==EPIPE) continue;
+ // read() from kmsg always fails on a pre-3.5 kernel.
+ if (len==-1 && errno==EINVAL) goto klogctl_mode;
+ if (len<1) break;
+
+ msg[len] = 0;
+ format_message(msg, 1);
+ }
+ close(fd);
+ } else {
+ char *data, *to, *from, *end;
+ int size;
+
+klogctl_mode:
+ // Figure out how much data we need, and fetch it.
+ if (!(size = TT.size)) size = xklogctl(10, 0, 0);
+ data = from = xmalloc(size+1);
+ data[size = xklogctl(3+(toys.optflags&FLAG_c), data, size)] = 0;
+
+ // Send each line to format_message.
+ to = data + size;
+ while (from < to) {
+ if (!(end = memchr(from, '\n', to-from))) break;
+ *end = 0;
+ format_message(from, 0);
+ from = end + 1;
+ }
+
+ if (CFG_TOYBOX_FREE) free(data);
+ }
+
+no_output:
+ // Set the log level?
+ if (toys.optflags & FLAG_n) xklogctl(8, 0, TT.level);
+
+ // Clear the buffer?
+ if (toys.optflags & (FLAG_C|FLAG_c)) xklogctl(5, 0, 0);
+}
diff --git a/toys/pending/dmesg.c b/toys/pending/dmesg.c
deleted file mode 100644
index 198f64a1..00000000
--- a/toys/pending/dmesg.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* dmesg.c - display/control kernel ring buffer.
- *
- * Copyright 2006, 2007 Rob Landley <rob@landley.net>
- *
- * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/dmesg.html
-
-// We care that FLAG_c is 1, so keep c at the end.
-USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc]", TOYFLAG_BIN))
-
-config DMESG
- bool "dmesg"
- default n
- help
- usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]
-
- Print or control the kernel ring buffer.
-
- -C Clear ring buffer without printing
- -c Clear ring buffer after printing
- -n Set kernel logging LEVEL (1-9)
- -r Raw output (with <level markers>)
- -S Use syslog(2) rather than /dev/kmsg
- -s Show the last SIZE many bytes
- -T Show human-readable timestamps
- -t Don't print timestamps
- -w Keep waiting for more output (aka --follow)
-*/
-
-#define FOR_dmesg
-#include "toys.h"
-#include <sys/klog.h>
-
-GLOBALS(
- long level;
- long size;
-
- int use_color;
- struct sysinfo info;
-)
-
-static void color(int c)
-{
- if (TT.use_color) printf("\033[%dm", c);
-}
-
-static void format_message(char *msg, int new) {
- unsigned long long time_s;
- unsigned long long time_us;
- int facpri, subsystem, pos;
- char *p, *text;
-
- // The new /dev/kmsg and the old syslog(2) formats differ slightly.
- if (new) {
- if (sscanf(msg, "%u,%*u,%llu,%*[^;];%n", &facpri, &time_us, &pos) != 2)
- return;
-
- time_s = time_us/1000000;
- time_us %= 1000000;
- } else {
- if (sscanf(msg, "<%u>[%llu.%llu] %n",
- &facpri, &time_s, &time_us, &pos) != 3)
- return;
- }
-
- // Drop extras after end of message text.
- text = msg + pos;
- if ((p = strchr(text, '\n'))) *p = 0;
-
- // Is there a subsystem? (The ": " is just a convention.)
- p = strstr(text, ": ");
- subsystem = p ? (p - text) : 0;
-
- // "Raw" is a lie for /dev/kmsg. In practice, it just means we show the
- // syslog facility/priority at the start of each line to emulate the
- // historical syslog(2) format.
- if (toys.optflags&FLAG_r) printf("<%d>", facpri);
-
- // Format the time.
- if (!(toys.optflags&FLAG_t)) {
- color(32);
- if (toys.optflags&FLAG_T) {
- time_t t = (time(NULL) - TT.info.uptime) + time_s;
- char *ts = ctime(&t);
-
- printf("[%.*s] ", (int)(strlen(ts) - 1), ts);
- } else {
- printf("[%5lld.%06lld] ", time_s, time_us);
- }
- color(0);
- }
-
- // Errors (or worse) are shown in red, subsystems are shown in yellow.
- if (subsystem) {
- color(33);
- printf("%.*s", subsystem, text);
- text += subsystem;
- color(0);
- }
- if (!((facpri&7) <= 3)) xputs(text);
- else {
- color(31);
- printf("%s", text);
- color(0);
- xputc('\n');
- }
-}
-
-static int xklogctl(int type, char *buf, int len)
-{
- int rc = klogctl(type, buf, len);
-
- if (rc<0) perror_exit("klogctl");
-
- return rc;
-}
-
-// Use klogctl for reading if we're on a pre-3.5 kernel.
-static void legacy_mode()
-{
- char *data, *to, *from;
- int size;
-
- // Figure out how much data we need, and fetch it.
- if (!(size = TT.size)) size = xklogctl(10, 0, 0);
- data = to = from = xmalloc(size+1);
- data[size = xklogctl(3 + (toys.optflags & FLAG_c), data, size)] = 0;
-
- // Break into messages (one per line) and send each one to format_message.
- to = data + size;
- while (from < to) {
- char *msg_end = memchr(from, '\n', (to-from));
-
- if (!msg_end) break;
- *msg_end = '\0';
- format_message(from, 0);
- from = msg_end + 1;
- }
-
- if (CFG_TOYBOX_FREE) free(data);
-}
-
-static void print_all(void)
-{
- if (toys.optflags&FLAG_T) sysinfo(&TT.info);
- if (toys.optflags&FLAG_S) return legacy_mode();
-
- // http://kernel.org/doc/Documentation/ABI/testing/dev-kmsg
-
- // Each read returns one message. By default, we block when there are no
- // more messages (--follow); O_NONBLOCK is needed for for usual behavior.
- int fd = xopen("/dev/kmsg", O_RDONLY | ((toys.optflags&FLAG_w)?0:O_NONBLOCK));
-
- // With /dev/kmsg, SYSLOG_ACTION_CLEAR (5) doesn't actually remove anything;
- // you need to seek to the last clear point.
- lseek(fd, 0, SEEK_DATA);
-
- while (1) {
- char msg[8192]; // CONSOLE_EXT_LOG_MAX.
- ssize_t len;
-
- // kmsg fails with EPIPE if we try to read while the buffer moves under
- // us; the next read will succeed and return the next available entry.
- do {
- len = read(fd, msg, sizeof(msg));
- } while (len == -1 && errno == EPIPE);
- // All reads from kmsg fail if you're on a pre-3.5 kernel.
- if (len == -1 && errno == EINVAL) {
- close(fd);
- return legacy_mode();
- }
- if (len <= 0) break;
-
- msg[len] = 0;
- format_message(msg, 1);
- }
- close(fd);
-}
-
-void dmesg_main(void)
-{
- TT.use_color = isatty(1);
-
- if (!(toys.optflags & (FLAG_C|FLAG_n))) print_all();
-
- // Set the log level?
- if (toys.optflags & FLAG_n) xklogctl(8, 0, TT.level);
-
- // Clear the buffer?
- if (toys.optflags & (FLAG_C|FLAG_c)) xklogctl(5, 0, 0);
-}
diff --git a/toys/posix/cpio.c b/toys/posix/cpio.c
index 5524dba2..90c8107f 100644
--- a/toys/posix/cpio.c
+++ b/toys/posix/cpio.c
@@ -16,7 +16,7 @@
* rdevmajor rdevminor namesize check
* This is the equiavlent of mode -H newc when using GNU CPIO.
-USE_CPIO(NEWTOY(cpio, "(no-preserve-owner)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
+USE_CPIO(NEWTOY(cpio, "(no-preserve-owner)(trailer)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
config CPIO
bool "cpio"
@@ -34,6 +34,7 @@ config CPIO
-t test files (list only, stdin=archive, stdout=list of files)
-v verbose (list files during create/extract)
--no-preserve-owner (don't set ownership during extract)
+ --trailer Add legacy trailer (prevents concatenation).
*/
#define FOR_cpio
@@ -113,8 +114,8 @@ void cpio_main(void)
int test = toys.optflags & FLAG_t, err = 0;
// Read header and name.
- xreadall(afd, toybuf, 110);
- if (memcmp(toybuf, "070701", 6)) error_exit("bad cpio magic");
+ if (!(size =readall(afd, toybuf, 110))) break;
+ if (size != 110 || memcmp(toybuf, "070701", 6)) error_exit("bad header");
tofree = name = strpad(afd, x8u(toybuf+94), 110);
if (!strcmp("TRAILER!!!", name)) {
if (CFG_TOYBOX_FREE) free(tofree);
@@ -275,9 +276,11 @@ void cpio_main(void)
}
free(name);
- memset(toybuf, 0, sizeof(toybuf));
- xwrite(afd, toybuf,
- sprintf(toybuf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0)+4);
+ if (FLAG_trailer) {
+ memset(toybuf, 0, sizeof(toybuf));
+ xwrite(afd, toybuf,
+ sprintf(toybuf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0)+4);
+ }
}
if (TT.archive) xclose(afd);
diff --git a/toys/posix/grep.c b/toys/posix/grep.c
index a95203a0..d1452cec 100644
--- a/toys/posix/grep.c
+++ b/toys/posix/grep.c
@@ -4,9 +4,11 @@
*
* See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html
*
- * TODO: -ABC
+ * TODO: --color, "Binary file %s matches"
+ *
+ * Posix doesn't even specify -r, documenting deviations from it is silly.
-USE_GREP(NEWTOY(grep, "C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]", TOYFLAG_BIN))
+USE_GREP(NEWTOY(grep, "S(exclude)*M(include)*C#B#A#ZzEFHabhinorsvwclqe*f*m#x[!wx][!EFw]", TOYFLAG_BIN))
USE_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN))
USE_FGREP(OLDTOY(fgrep, grep, TOYFLAG_BIN))
@@ -14,22 +16,27 @@ config GREP
bool "grep"
default y
help
- usage: grep [-EFivwcloqsHbhn] [-A NUM] [-m MAX] [-e REGEX]... [-f REGFILE] [FILE]...
+ usage: grep [-EFrivwcloqsHbhn] [-ABC NUM] [-m MAX] [-e REGEX]... [-MS PATTERN]... [-f REGFILE] [FILE]...
Show lines matching regular expressions. If no -e, first argument is
regular expression to match. With no files (or "-" filename) read stdin.
Returns 0 if matched, 1 if no match found.
-e Regex to match. (May be repeated.)
- -f File containing regular expressions to match.
+ -f File listing regular expressions to match.
+
+ file search:
+ -r Recurse into subdirectories (defaults FILE to ".")
+ -M Match filename pattern (--include)
+ -S Skip filename pattern (--exclude)
match type:
-A Show NUM lines after -B Show NUM lines before match
-C NUM lines context (A+B) -E extended regex syntax
-F fixed (literal match) -i case insensitive
- -m match MAX many lines -r recursive (on dir)
- -v invert match -w whole word (implies -E)
- -x whole line -z input NUL terminated
+ -m match MAX many lines -v invert match
+ -w whole word (implies -E) -x whole line
+ -z input NUL terminated
display modes: (default: matched line)
-c count of matching lines -l show matching filenames
@@ -62,8 +69,11 @@ GLOBALS(
long a;
long b;
long c;
+ struct arg_list *M;
+ struct arg_list *S;
char indelim, outdelim;
+ int found;
)
// Emit line with various potential prefixes and delimiter
@@ -81,12 +91,18 @@ static void outline(char *line, char dash, char *name, long lcount, long bcount,
static void do_grep(int fd, char *name)
{
struct double_list *dlb = 0;
- FILE *file = xfdopen(fd, "r");
+ FILE *file = fdopen(fd, "r");
long lcount = 0, mcount = 0, offset = 0, after = 0, before = 0;
char *bars = 0;
if (!fd) name = "(standard input)";
+ if (!file) {
+ perror_msg("%s", name);
+
+ return;
+ }
+
// Loop through lines of input
for (;;) {
char *line = 0, *start;
@@ -96,7 +112,10 @@ static void do_grep(int fd, char *name)
int mmatch = 0;
lcount++;
- if (0 > (len = getdelim(&line, &unused, TT.indelim, file))) break;
+ errno = 0;
+ len = getdelim(&line, &unused, TT.indelim, file);
+ if (errno) perror_msg("%s", name);
+ if (len<1) break;
if (line[len-1] == TT.indelim) line[len-1] = 0;
start = line;
@@ -176,8 +195,11 @@ static void do_grep(int fd, char *name)
bars = 0;
}
mmatch++;
- toys.exitval = 0;
- if (toys.optflags & FLAG_q) xexit();
+ TT.found = 1;
+ if (toys.optflags & FLAG_q) {
+ toys.exitval = 0;
+ xexit();
+ }
if (toys.optflags & FLAG_l) {
xprintf("%s%c", name, TT.outdelim);
free(line);
@@ -315,6 +337,19 @@ static int do_grep_r(struct dirtree *new)
if (!dirtree_notdotdot(new)) return 0;
if (S_ISDIR(new->st.st_mode)) return DIRTREE_RECURSE;
+ if (TT.S || TT.M) {
+ struct arg_list *al;
+
+ for (al = TT.S; al; al = al->next)
+ if (!fnmatch(al->arg, new->name, 0)) return 0;
+
+ if (TT.M) {
+ for (al = TT.M; al; al = al->next)
+ if (!fnmatch(al->arg, new->name, 0)) break;
+
+ if (!al) return 0;
+ }
+ }
// "grep -r onefile" doesn't show filenames, but "grep -r onedir" should.
if (new->parent && !(toys.optflags & FLAG_h)) toys.optflags |= FLAG_H;
@@ -330,6 +365,9 @@ void grep_main(void)
{
char **ss = toys.optargs;
+ // Grep exits with 2 for errors
+ toys.exitval = 2;
+
if (!TT.a) TT.a = TT.c;
if (!TT.b) TT.b = TT.c;
@@ -351,7 +389,6 @@ void grep_main(void)
if (!(toys.optflags & FLAG_h) && toys.optc>1) toys.optflags |= FLAG_H;
- toys.exitval = 1;
if (toys.optflags & FLAG_s) {
close(2);
xopen_stdio("/dev/null", O_RDWR);
@@ -364,4 +401,5 @@ void grep_main(void)
else dirtree_read(*ss, do_grep_r);
}
} else loopfiles_rw(ss, O_RDONLY|WARN_ONLY, 0, do_grep);
+ toys.exitval = !TT.found;
}
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index f6906716..a0dc53f5 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -128,10 +128,9 @@ config PS
config TOP
bool "top"
- depends on TOP_COMMON
default y
help
- usage: top [-H] [-k FIELD,] [-o FIELD,] [-s SORT]
+ usage: top [-Hbq] [-k FIELD,] [-o FIELD,] [-s SORT] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]
Show process activity in real time.
@@ -140,14 +139,22 @@ config TOP
-o Show FIELDS (def PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,CMDLINE)
-O Add FIELDS (replacing PR,NI,VIRT,RES,SHR,S from default)
-s Sort by field number (1-X, default 9)
+ -b Batch mode (no tty)
+ -d Delay SECONDS between each cycle (default 3)
+ -n Exit after NUMBER iterations
+ -p Show these PIDs
+ -u Show these USERs
+ -q Quiet (no header lines)
+
+ Cursor LEFT/RIGHT to change sort, UP/DOWN move list, space to force
+ update, R to reverse sort, Q to exit.
# Requires CONFIG_IRQ_TIME_ACCOUNTING in the kernel for /proc/$$/io
config IOTOP
bool "iotop"
- depends on TOP_COMMON
default y
help
- usage: iotop [-AaKO]
+ usage: iotop [-AaKObq] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]
Rank processes by I/O.
@@ -158,13 +165,6 @@ config IOTOP
-O Only show processes doing I/O
-o Show FIELDS (default PID,PR,USER,[D]READ,[D]WRITE,SWAP,[D]IO,COMM)
-s Sort by field number (0-X, default 6)
-
-config TOP_COMMON
- bool
- default y
- help
- usage: * [-bq] [-n NUMBER] [-d SECONDS] [-p PID,] [-u USER,]
-
-b Batch mode (no tty)
-d Delay SECONDS between each cycle (default 3)
-n Exit after NUMBER iterations
@@ -178,9 +178,8 @@ config TOP_COMMON
config PGREP
bool "pgrep"
default y
- depends on PGKILL_COMMON
help
- usage: pgrep [-cl] [-d DELIM] [-L SIGNAL] [PATTERN]
+ usage: pgrep [-clfnovx] [-d DELIM] [-L SIGNAL] [PATTERN] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,] [-t TERM,] [-U UID,] [-u EUID,]
Search for process(es). PATTERN is an extended regular expression checked
against command names.
@@ -189,23 +188,27 @@ config PGREP
-d Use DELIM instead of newline
-L Send SIGNAL instead of printing name
-l Show command name
+ -f Check full command line for PATTERN
+ -G Match real Group ID(s)
+ -g Match Process Group(s) (0 is current user)
+ -n Newest match only
+ -o Oldest match only
+ -P Match Parent Process ID(s)
+ -s Match Session ID(s) (0 for current)
+ -t Match Terminal(s)
+ -U Match real User ID(s)
+ -u Match effective User ID(s)
+ -v Negate the match
+ -x Match whole command (not substring)
config PKILL
bool "pkill"
default y
- depends on PGKILL_COMMON
help
- usage: pkill [-SIGNAL|-l SIGNAL] [PATTERN]
+ usage: pkill [-fnovx] [-SIGNAL|-l SIGNAL] [PATTERN] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,] [-t TERM,] [-U UID,] [-u EUID,]
-l Send SIGNAL (default SIGTERM)
-V verbose
-
-config PGKILL_COMMON
- bool
- default y
- help
- usage: * [-fnovx] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,] [-t TERM,] [-U UID,] [-u EUID,]
-
-f Check full command line for PATTERN
-G Match real Group ID(s)
-g Match Process Group(s) (0 is current user)
diff --git a/www/conduct.html b/www/conduct.html
new file mode 100755
index 00000000..07658956
--- /dev/null
+++ b/www/conduct.html
@@ -0,0 +1,32 @@
+<html><head><title>Toybox Code of Conduct</title>
+<!--#include file="header.html" -->
+
+<p>Toybox's code of conduct used to just link to <a href=https://engineering.twitter.com/opensource/code-of-conduct>twitter's</a>. When that page
+went down we mirrored it here (with different contact info).</p>
+
+<hr>
+
+<p>This code of conduct outlines our expectations for participants within the toybox community, as well as steps to reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all and expect our code of conduct to be honored. Anyone who violates this code of conduct may be banned from the community.</p>
+<p>Our open source community strives to:</p>
+<ol><li><p><strong>Be friendly and patient.</strong></p></li>
+<li><p><strong>Be welcoming:</strong> We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.</p></li>
+<li><p><strong>Be considerate:</strong> Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone elses primary language.</p></li>
+<li><p><strong>Be respectful:</strong> Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. Its important to remember that a community where people feel uncomfortable or threatened is not a productive one.</p></li>
+<li><p><strong>Be careful in the words that you choose:</strong> we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior arent acceptable. This includes, but is not limited to: Violent threats or language directed against another person, Discriminatory jokes and language, Posting sexually explicit or violent material, Posting (or threatening to post) other peoples personally identifying information (doxing), Personal insults, especially those using racist or sexist terms, Unwelcome sexual attention, Advocating for, or encouraging, any of the above behavior, Repeated harassment of others. In general, if someone asks you to stop, then stop.</p></li>
+<li><p><strong>When we disagree:</strong> try to understand why: Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that were different. The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesnt mean that theyre wrong. Dont forget that it is human to err and blaming each other doesnt get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.</p></li>
+</ol><p>This code is not exhaustive or complete. It serves to distill our common understanding of a collaborative, shared environment, and goals. We expect it to be followed in spirit as much as in the letter.</p>
+<h5>Diversity Statement</h5>
+<p>We encourage everyone to participate and are committed to building a community for all. Although we may not be able to satisfy everyone, we all agree that everyone is equal. Whenever a participant has made a mistake, we expect them to take responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and respectfully, and do our best to right the wrong.</p>
+<p>Although this list cannot be exhaustive, we explicitly honor diversity in age, gender, gender identity or expression, culture, ethnicity, language, national origin, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, and technical ability. We will not tolerate discrimination based on any of the protected characteristics above, including participants with disabilities.</p>
+<h5>Reporting Issues</h5>
+<p>If you experience or witness unacceptable behavior--or have any other concerns--please report it by contacting the project maintainer (rob@landley.net). All reports will be handled with discretion. In your report please include:</p>
+<ul><li>Your contact information.</li>
+<li>Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link.</li>
+<li>Any additional information that may be helpful.</li>
+</ul><p>After filing a report, a representative will contact you personally. If the person who is harassing you is part of the response team, they will recuse themselves from handling your incident. A representative will then review the incident, follow up with any additional questions, and make a decision as to how to respond. We will respect confidentiality requests for the purpose of protecting victims of abuse.</p>
+<p>Anyone asked to stop unacceptable behavior is expected to comply immediately. If an individual engages in unacceptable behavior, the representative may take any action they deem appropriate, up to and including a permanent ban from our community without warning.</p>
+<ul></ul><h5>Thanks</h5>
+<p>This code of conduct is based on the <a href="https://github.com/todogroup/opencodeofconduct">Open Code of Conduct</a> v1.0.
+We are thankful for their work and all the communities who have paved the way with code of conducts.</p>
+
+<!--#include file="footer.html" -->
diff --git a/www/header.html b/www/header.html
index e3cd2d0c..0d5baa90 100644
--- a/www/header.html
+++ b/www/header.html
@@ -37,6 +37,7 @@
<li><a href="/notes.html">Maintainer's Blog</a></li>
<li><a href=cleanup.html>Cleanup</a></li>
<li><a href=http://www.ohloh.net/p/toybox-landley>Statistics</a></li>
+ <li><a href=conduct.html>Code of Conduct</a></li>
</ul>
</td>