Merge "Remove no longer used configuration." into main
diff --git a/METADATA b/METADATA
index 8929f6a..23580bc 100644
--- a/METADATA
+++ b/METADATA
@@ -8,13 +8,13 @@
   license_type: UNENCUMBERED
   last_upgrade_date {
     year: 2025
-    month: 1
-    day: 21
+    month: 2
+    day: 25
   }
   homepage: "https://landley.net/toybox/"
   identifier {
     type: "Git"
     value: "https://github.com/landley/toybox"
-    version: "7eaddbdb9c1712801ddf131ed79ead0c981ffcb1"
+    version: "eccdbbc338e83356033fa473b17d3e693e4dea65"
   }
 }
diff --git a/android/device/generated/flags.h b/android/device/generated/flags.h
index 48342b0..a29e12f 100644
--- a/android/device/generated/flags.h
+++ b/android/device/generated/flags.h
@@ -2446,9 +2446,9 @@
 #undef FLAG_no_backup_if_mismatch
 #endif
 
-// pgrep ?cld:u*U*t*s*P*g*G*fnovxL:[-no] ?cld:u*U*t*s*P*g*G*fnovxL:[-no]
+// pgrep acld:u*U*t*s*P*g*G*fnovxL:[-no] acld:u*U*t*s*P*g*G*fnovxL:[-no]
 #undef OPTSTR_pgrep
-#define OPTSTR_pgrep "?cld:u*U*t*s*P*g*G*fnovxL:[-no]"
+#define OPTSTR_pgrep "acld:u*U*t*s*P*g*G*fnovxL:[-no]"
 #ifdef CLEANUP_pgrep
 #undef CLEANUP_pgrep
 #undef FOR_pgrep
@@ -2468,6 +2468,7 @@
 #undef FLAG_d
 #undef FLAG_l
 #undef FLAG_c
+#undef FLAG_a
 #endif
 
 // pidof so:x so:x
@@ -3501,6 +3502,16 @@
 #undef FLAG_i
 #endif
 
+// trap   lp
+#undef OPTSTR_trap
+#define OPTSTR_trap "lp"
+#ifdef CLEANUP_trap
+#undef CLEANUP_trap
+#undef FOR_trap
+#undef FLAG_p
+#undef FLAG_l
+#endif
+
 // true    
 #undef OPTSTR_true
 #define OPTSTR_true 0
@@ -6223,6 +6234,7 @@
 #define FLAG_d (1LL<<13)
 #define FLAG_l (1LL<<14)
 #define FLAG_c (1LL<<15)
+#define FLAG_a (1LL<<16)
 #endif
 
 #ifdef FOR_pidof
@@ -7179,6 +7191,15 @@
 #define FLAG_i (1LL<<19)
 #endif
 
+#ifdef FOR_trap
+#define CLEANUP_trap
+#ifndef TT
+#define TT this.trap
+#endif
+#define FLAG_p (FORCED_FLAG<<0)
+#define FLAG_l (FORCED_FLAG<<1)
+#endif
+
 #ifdef FOR_true
 #define CLEANUP_true
 #ifndef TT
diff --git a/android/device/generated/help.h b/android/device/generated/help.h
index 225268b..287c4e5 100644
--- a/android/device/generated/help.h
+++ b/android/device/generated/help.h
@@ -396,6 +396,8 @@
 
 #define HELP_wait "usage: wait [-n] [ID...]\n\nWait for background processes to exit, returning its exit code.\nID can be PID or job, with no IDs waits for all backgrounded processes.\n\n-n	Wait for next process to exit"
 
+#define HELP_trap "usage: trap [-l] [[COMMAND] SIGNAL]\n\nRun COMMAND as handler for signal. With no arguments, list active handlers.\nThe COMMAND \"-\" resets the signal to default.\n\n-l	List signals.\n\nThe special signal EXIT gets called before the shell exits, RETURN when\na function or source returns, and DEBUG is called before each command."
+
 #define HELP_source "usage: source FILE [ARGS...]\n\nRead FILE and execute commands. Any ARGS become positional parameters."
 
 #define HELP_shift "usage: shift [N]\n\nSkip N (default 1) positional parameters, moving $1 and friends along the list.\nDoes not affect $0."
@@ -572,7 +574,7 @@
 
 #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)"
 
-#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)"
+#define HELP_pgrep "usage: pgrep [-aclfnovx] [-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-a	Show the full command line\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)"
 
 #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-H	Show threads\n-K	Kilobytes\n-k	Fallback sort FIELDS (default -[D]IO,-ETIME,-PID)\n-m	Maximum number of tasks to show\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."
 
diff --git a/android/device/generated/newtoys.h b/android/device/generated/newtoys.h
index de4d154..f86bf7d 100644
--- a/android/device/generated/newtoys.h
+++ b/android/device/generated/newtoys.h
@@ -220,7 +220,7 @@
 USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_USR|TOYFLAG_BIN))
 USE_PATCH(NEWTOY(patch, ">2(no-backup-if-mismatch)(dry-run)F#g#fulp#v(verbose)@d:i:Rs(quiet)[!sv]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PGREP(NEWTOY(pgrep, "acld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_PIDOF(NEWTOY(pidof, "so:x", TOYFLAG_BIN))
 USE_PING(NEWTOY(ping, "<1>1m#t#<0>255=64c#<0=3s#<0>4064=56i%W#<0=3w#<0qf46I:[-46]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
 USE_PING(OLDTOY(ping6, ping, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
@@ -307,6 +307,7 @@
 USE_TR(NEWTOY(tr, "^<1>2Ccstd[+cC]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TRACEROUTE(NEWTOY(traceroute, "<1>2i:f#<1>255=1z#<0>86400=0g*w#<0>86400=5t#<0>255=0s:q#<1>255=3p#<1>65535=33434m#<1>255=30rvndlIUF64", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_TRACEROUTE(OLDTOY(traceroute6,traceroute, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
+USE_SH(NEWTOY(trap, "lp", TOYFLAG_NOFORK))
 USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
 USE_TRUNCATE(NEWTOY(truncate, "<1s:|c", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TS(NEWTOY(ts, "ims", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
diff --git a/android/linux/generated/flags.h b/android/linux/generated/flags.h
index b92381d..d6f7d6d 100644
--- a/android/linux/generated/flags.h
+++ b/android/linux/generated/flags.h
@@ -2446,9 +2446,9 @@
 #undef FLAG_no_backup_if_mismatch
 #endif
 
-// pgrep ?cld:u*U*t*s*P*g*G*fnovxL:[-no] ?cld:u*U*t*s*P*g*G*fnovxL:[-no]
+// pgrep acld:u*U*t*s*P*g*G*fnovxL:[-no] acld:u*U*t*s*P*g*G*fnovxL:[-no]
 #undef OPTSTR_pgrep
-#define OPTSTR_pgrep "?cld:u*U*t*s*P*g*G*fnovxL:[-no]"
+#define OPTSTR_pgrep "acld:u*U*t*s*P*g*G*fnovxL:[-no]"
 #ifdef CLEANUP_pgrep
 #undef CLEANUP_pgrep
 #undef FOR_pgrep
@@ -2468,6 +2468,7 @@
 #undef FLAG_d
 #undef FLAG_l
 #undef FLAG_c
+#undef FLAG_a
 #endif
 
 // pidof   so:x
@@ -3501,6 +3502,16 @@
 #undef FLAG_i
 #endif
 
+// trap   lp
+#undef OPTSTR_trap
+#define OPTSTR_trap "lp"
+#ifdef CLEANUP_trap
+#undef CLEANUP_trap
+#undef FOR_trap
+#undef FLAG_p
+#undef FLAG_l
+#endif
+
 // true    
 #undef OPTSTR_true
 #define OPTSTR_true 0
@@ -6223,6 +6234,7 @@
 #define FLAG_d (1LL<<13)
 #define FLAG_l (1LL<<14)
 #define FLAG_c (1LL<<15)
+#define FLAG_a (1LL<<16)
 #endif
 
 #ifdef FOR_pidof
@@ -7179,6 +7191,15 @@
 #define FLAG_i (FORCED_FLAG<<19)
 #endif
 
+#ifdef FOR_trap
+#define CLEANUP_trap
+#ifndef TT
+#define TT this.trap
+#endif
+#define FLAG_p (FORCED_FLAG<<0)
+#define FLAG_l (FORCED_FLAG<<1)
+#endif
+
 #ifdef FOR_true
 #define CLEANUP_true
 #ifndef TT
diff --git a/android/linux/generated/help.h b/android/linux/generated/help.h
index a3e6aa4..42cca1f 100644
--- a/android/linux/generated/help.h
+++ b/android/linux/generated/help.h
@@ -398,6 +398,8 @@
 
 #define HELP_wait "usage: wait [-n] [ID...]\n\nWait for background processes to exit, returning its exit code.\nID can be PID or job, with no IDs waits for all backgrounded processes.\n\n-n	Wait for next process to exit"
 
+#define HELP_trap "usage: trap [-l] [[COMMAND] SIGNAL]\n\nRun COMMAND as handler for signal. With no arguments, list active handlers.\nThe COMMAND \"-\" resets the signal to default.\n\n-l	List signals.\n\nThe special signal EXIT gets called before the shell exits, RETURN when\na function or source returns, and DEBUG is called before each command."
+
 #define HELP_source "usage: source FILE [ARGS...]\n\nRead FILE and execute commands. Any ARGS become positional parameters."
 
 #define HELP_shift "usage: shift [N]\n\nSkip N (default 1) positional parameters, moving $1 and friends along the list.\nDoes not affect $0."
@@ -574,7 +576,7 @@
 
 #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)"
 
-#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)"
+#define HELP_pgrep "usage: pgrep [-aclfnovx] [-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-a	Show the full command line\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)"
 
 #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-H	Show threads\n-K	Kilobytes\n-k	Fallback sort FIELDS (default -[D]IO,-ETIME,-PID)\n-m	Maximum number of tasks to show\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."
 
diff --git a/android/linux/generated/newtoys.h b/android/linux/generated/newtoys.h
index de4d154..f86bf7d 100644
--- a/android/linux/generated/newtoys.h
+++ b/android/linux/generated/newtoys.h
@@ -220,7 +220,7 @@
 USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_USR|TOYFLAG_BIN))
 USE_PATCH(NEWTOY(patch, ">2(no-backup-if-mismatch)(dry-run)F#g#fulp#v(verbose)@d:i:Rs(quiet)[!sv]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PGREP(NEWTOY(pgrep, "acld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_PIDOF(NEWTOY(pidof, "so:x", TOYFLAG_BIN))
 USE_PING(NEWTOY(ping, "<1>1m#t#<0>255=64c#<0=3s#<0>4064=56i%W#<0=3w#<0qf46I:[-46]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
 USE_PING(OLDTOY(ping6, ping, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
@@ -307,6 +307,7 @@
 USE_TR(NEWTOY(tr, "^<1>2Ccstd[+cC]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TRACEROUTE(NEWTOY(traceroute, "<1>2i:f#<1>255=1z#<0>86400=0g*w#<0>86400=5t#<0>255=0s:q#<1>255=3p#<1>65535=33434m#<1>255=30rvndlIUF64", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_TRACEROUTE(OLDTOY(traceroute6,traceroute, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
+USE_SH(NEWTOY(trap, "lp", TOYFLAG_NOFORK))
 USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
 USE_TRUNCATE(NEWTOY(truncate, "<1s:|c", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TS(NEWTOY(ts, "ims", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
diff --git a/android/mac/generated/flags.h b/android/mac/generated/flags.h
index a7b86a7..b6b410f 100644
--- a/android/mac/generated/flags.h
+++ b/android/mac/generated/flags.h
@@ -2446,9 +2446,9 @@
 #undef FLAG_no_backup_if_mismatch
 #endif
 
-// pgrep   ?cld:u*U*t*s*P*g*G*fnovxL:[-no]
+// pgrep   acld:u*U*t*s*P*g*G*fnovxL:[-no]
 #undef OPTSTR_pgrep
-#define OPTSTR_pgrep "?cld:u*U*t*s*P*g*G*fnovxL:[-no]"
+#define OPTSTR_pgrep "acld:u*U*t*s*P*g*G*fnovxL:[-no]"
 #ifdef CLEANUP_pgrep
 #undef CLEANUP_pgrep
 #undef FOR_pgrep
@@ -2468,6 +2468,7 @@
 #undef FLAG_d
 #undef FLAG_l
 #undef FLAG_c
+#undef FLAG_a
 #endif
 
 // pidof   so:x
@@ -3501,6 +3502,16 @@
 #undef FLAG_i
 #endif
 
+// trap   lp
+#undef OPTSTR_trap
+#define OPTSTR_trap "lp"
+#ifdef CLEANUP_trap
+#undef CLEANUP_trap
+#undef FOR_trap
+#undef FLAG_p
+#undef FLAG_l
+#endif
+
 // true    
 #undef OPTSTR_true
 #define OPTSTR_true 0
@@ -6223,6 +6234,7 @@
 #define FLAG_d (FORCED_FLAG<<13)
 #define FLAG_l (FORCED_FLAG<<14)
 #define FLAG_c (FORCED_FLAG<<15)
+#define FLAG_a (FORCED_FLAG<<16)
 #endif
 
 #ifdef FOR_pidof
@@ -7179,6 +7191,15 @@
 #define FLAG_i (FORCED_FLAG<<19)
 #endif
 
+#ifdef FOR_trap
+#define CLEANUP_trap
+#ifndef TT
+#define TT this.trap
+#endif
+#define FLAG_p (FORCED_FLAG<<0)
+#define FLAG_l (FORCED_FLAG<<1)
+#endif
+
 #ifdef FOR_true
 #define CLEANUP_true
 #ifndef TT
diff --git a/android/mac/generated/help.h b/android/mac/generated/help.h
index a3e6aa4..42cca1f 100644
--- a/android/mac/generated/help.h
+++ b/android/mac/generated/help.h
@@ -398,6 +398,8 @@
 
 #define HELP_wait "usage: wait [-n] [ID...]\n\nWait for background processes to exit, returning its exit code.\nID can be PID or job, with no IDs waits for all backgrounded processes.\n\n-n	Wait for next process to exit"
 
+#define HELP_trap "usage: trap [-l] [[COMMAND] SIGNAL]\n\nRun COMMAND as handler for signal. With no arguments, list active handlers.\nThe COMMAND \"-\" resets the signal to default.\n\n-l	List signals.\n\nThe special signal EXIT gets called before the shell exits, RETURN when\na function or source returns, and DEBUG is called before each command."
+
 #define HELP_source "usage: source FILE [ARGS...]\n\nRead FILE and execute commands. Any ARGS become positional parameters."
 
 #define HELP_shift "usage: shift [N]\n\nSkip N (default 1) positional parameters, moving $1 and friends along the list.\nDoes not affect $0."
@@ -574,7 +576,7 @@
 
 #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)"
 
-#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)"
+#define HELP_pgrep "usage: pgrep [-aclfnovx] [-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-a	Show the full command line\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)"
 
 #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-H	Show threads\n-K	Kilobytes\n-k	Fallback sort FIELDS (default -[D]IO,-ETIME,-PID)\n-m	Maximum number of tasks to show\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."
 
diff --git a/android/mac/generated/newtoys.h b/android/mac/generated/newtoys.h
index de4d154..f86bf7d 100644
--- a/android/mac/generated/newtoys.h
+++ b/android/mac/generated/newtoys.h
@@ -220,7 +220,7 @@
 USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_USR|TOYFLAG_BIN))
 USE_PATCH(NEWTOY(patch, ">2(no-backup-if-mismatch)(dry-run)F#g#fulp#v(verbose)@d:i:Rs(quiet)[!sv]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PGREP(NEWTOY(pgrep, "acld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_PIDOF(NEWTOY(pidof, "so:x", TOYFLAG_BIN))
 USE_PING(NEWTOY(ping, "<1>1m#t#<0>255=64c#<0=3s#<0>4064=56i%W#<0=3w#<0qf46I:[-46]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
 USE_PING(OLDTOY(ping6, ping, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
@@ -307,6 +307,7 @@
 USE_TR(NEWTOY(tr, "^<1>2Ccstd[+cC]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TRACEROUTE(NEWTOY(traceroute, "<1>2i:f#<1>255=1z#<0>86400=0g*w#<0>86400=5t#<0>255=0s:q#<1>255=3p#<1>65535=33434m#<1>255=30rvndlIUF64", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_TRACEROUTE(OLDTOY(traceroute6,traceroute, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
+USE_SH(NEWTOY(trap, "lp", TOYFLAG_NOFORK))
 USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
 USE_TRUNCATE(NEWTOY(truncate, "<1s:|c", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TS(NEWTOY(ts, "ims", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
diff --git a/main.c b/main.c
index 2d3fc2e..69cc8af 100644
--- a/main.c
+++ b/main.c
@@ -240,8 +240,12 @@
   // so convert to integers. (LP64 says sizeof(long)==sizeof(pointer).)
   // Signed typecast so stack growth direction is irrelevant: we're measuring
   // the distance between two pointers on the same stack, hence the labs().
-  if (!CFG_TOYBOX_NORECURSE && toys.stacktop)
+  if (!CFG_TOYBOX_NORECURSE && toys.stacktop) {
+    int i;
+
     if (labs((long)toys.stacktop-(long)&which)>24000) return;
+    for (i = 0; i<NSIG; i++) signal(i, SIG_DFL);
+  }
 
   // Return if we need to re-exec to acquire root via suid bit.
   if (toys.which && (which->flags&TOYFLAG_ROOTONLY) && toys.wasroot) return;
diff --git a/scripts/mkstatus.py b/scripts/mkstatus.py
index 41a1bed..b9b333c 100755
--- a/scripts/mkstatus.py
+++ b/scripts/mkstatus.py
@@ -55,7 +55,7 @@
         ("sash_cmd", "", '#%s#'), ("sbase_cmd", "", '@%s@'),
         ("beastiebox_cmd", "", '*%s*'), ("tizen_cmd", "", '$%s$'),
         ("fhs_cmd", "", '-%s-'), ("yocto_cmd", "", ".%s."),
-        ("shell", "", "%%%s%%"),
+        ("buildroot_cmd", "", "~%s~"), ("shell", "", "%%%s%%"),
         ("request", '<a href="https://man7.org/linux/man-pages/man1/%s.1.html">%%s</a>', '+%s+')]
 
 def categorize(reverse, i, skippy=""):
diff --git a/tests/pgrep.test b/tests/pgrep.test
index 8db848f..5957006 100644
--- a/tests/pgrep.test
+++ b/tests/pgrep.test
@@ -11,7 +11,7 @@
 #testing "name" "command" "result" "infile" "stdin"
 
 # Starting processes to test pgrep command
-yes >/dev/null &
+yes and no >/dev/null &
 proc=$!
 #echo "# Process created with id: $proc"
 sleep .1
@@ -24,11 +24,21 @@
 testing "wildCardPattern" "pgrep ^y.*s$" "$proc\n" "" ""
 testing "-l pattern" "pgrep -l yes" "$proc yes\n" "" ""
 testing "-f pattern" "pgrep -f yes" "$proc\n" "" ""
+testing "-a pattern" "pgrep -a yes" "$proc yes and no\n" "" ""
+testing "-la pattern" "pgrep -la yes" "$proc yes and no\n" "" ""
+testing "-fa pattern" "pgrep -fa yes" "$proc yes and no\n" "" ""
+testing "-lf pattern" "pgrep -lf yes" "$proc yes\n" "" ""
+testing "-fa pattern" "pgrep -fa yes" "$proc yes and no\n" "" ""
+testing "-lfa pattern" "pgrep -lfa yes" "$proc yes and no\n" "" ""
 testing "-n pattern" "pgrep -n yes" "$proc\n" "" ""
 testing "-o pattern" "pgrep -o yes" "$proc\n" "" ""
 testing "-s" "pgrep -s $session_id yes" "$proc\n" "" ""
 testing "-P" "pgrep -P $proc_parent yes" "$proc\n" "" ""
 
+testing "-f 'full command line'" "pgrep -f 'yes and no'" "$proc\n" "" ""
+testing "-l 'full command line nomatch'" "pgrep -l 'yes and no'" "" "" ""
+testing "-a 'full command line nomatch'" "pgrep -a 'yes and no'" "" "" ""
+
 testing "return success" "pgrep yes && echo success" "$proc\nsuccess\n" "" ""
 testing "return failure" "pgrep almost-certainly-not || echo failure" \
     "failure\n" "" ""
diff --git a/tests/sh.test b/tests/sh.test
index 27555c7..9b81790 100644
--- a/tests/sh.test
+++ b/tests/sh.test
@@ -733,6 +733,9 @@
 testing 'if; is a syntax error but if $EMPTY; is not' \
   'if $NONE; then echo hello; fi' 'hello\n' '' ''
 
+testing 'trap1' $'trap \'echo T=$?;false\' USR1;kill -s usr1 $$;echo A=$?' \
+  'T=0\nA=0\n' '' ''
+
 # TODO finish variable list from shell init
 
 # $# $? $- $! $0  # $$
diff --git a/toys/other/modinfo.c b/toys/other/modinfo.c
index e1a64ba..5a94a4f 100644
--- a/toys/other/modinfo.c
+++ b/toys/other/modinfo.c
@@ -64,7 +64,7 @@
 
   for (i=0; i<ARRAY_LEN(modinfo_tags); i++) {
     char *field = modinfo_tags[i], *p = buf;
-    int slen = sprintf(toybuf, "%s=", field);
+    int slen = sprintf(toybuf, "%c%s=", 0, field);
 
     while (p && p < end) {
       p = memmem(p, end-p, toybuf, slen);
diff --git a/toys/pending/crontab.c b/toys/pending/crontab.c
index 575398f..ced5755 100644
--- a/toys/pending/crontab.c
+++ b/toys/pending/crontab.c
@@ -234,6 +234,7 @@
   int fdin, fdout;
 
   snprintf(toybuf, sizeof(toybuf), "%s%s", TT.cdir, dest);
+  unlink(toybuf);
   fdout = xcreate(toybuf, O_WRONLY|O_CREAT|O_TRUNC, 0600);
   fdin = xopenro(src);
   xsendfile(fdin, fdout);
diff --git a/toys/pending/getty.c b/toys/pending/getty.c
index 7d0f9b1..1bd795d 100644
--- a/toys/pending/getty.c
+++ b/toys/pending/getty.c
@@ -149,6 +149,7 @@
       else if (ch == 'r') xputsn(TT.uts.release);
       else if (ch == 's') xputsn(TT.uts.sysname);
       else if (ch == 'l') xputsn(TT.tty_name);
+      else if (ch == '\\') xputc(ch);
       else printf("<bad escape>");
     } else xputc(ch);
   }
diff --git a/toys/pending/hexdump.c b/toys/pending/hexdump.c
index b688fc4..7d824c6 100644
--- a/toys/pending/hexdump.c
+++ b/toys/pending/hexdump.c
@@ -28,7 +28,7 @@
 
 config HD
   bool "hd"
-  default HEXDUMP
+  default n
   help
     usage: hd [FILE...]
 
@@ -151,5 +151,5 @@
   else TT.fmt = " %04x";
 
   loopfiles(toys.optargs, do_hexdump);
-  FLAG(C) ? printf("%08llx\n", TT.pos) : printf("%07llx\n", TT.pos);
+  printf("%0*llx\n", 7+FLAG(C), TT.pos);
 }
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index 921bc44..96368b5 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -60,6 +60,7 @@
 USE_SH(NEWTOY(shift, ">1", TOYFLAG_NOFORK))
 USE_SH(NEWTOY(source, "<1", TOYFLAG_NOFORK))
 USE_SH(OLDTOY(., source, TOYFLAG_NOFORK))
+USE_SH(NEWTOY(trap, "lp", TOYFLAG_NOFORK))
 USE_SH(NEWTOY(unset, "fvn[!fv]", TOYFLAG_NOFORK))
 USE_SH(NEWTOY(wait, "n", TOYFLAG_NOFORK))
 
@@ -313,6 +314,21 @@
 
     Read FILE and execute commands. Any ARGS become positional parameters.
 
+config TRAP
+  bool
+  default n
+  depends on SH
+  help
+    usage: trap [-l] [[COMMAND] SIGNAL]
+
+    Run COMMAND as handler for signal. With no arguments, list active handlers.
+    The COMMAND "-" resets the signal to default.
+
+    -l	List signals.
+
+    The special signal EXIT gets called before the shell exits, RETURN when
+    a function or source returns, and DEBUG is called before each command.
+
 config WAIT
   bool
   default n
@@ -341,9 +357,10 @@
 
   // keep SECONDS here: used to work around compiler limitation in run_command()
   long long SECONDS;
-  char *isexec, *wcpat;
+  char *isexec, *wcpat, *traps[NSIG+2];
   unsigned options, jobcnt;
   int hfd, pid, bangpid, recursion;
+  struct double_list *nextsig;
   jmp_buf forkchild;
 
   // Callable function array
@@ -371,7 +388,7 @@
       long flags;
       char *str;
     } *vars;
-    long varslen, varscap, shift, lineno;
+    long varslen, varscap, shift, lineno, signal;
 
     struct sh_function *function;
     FILE *source;
@@ -445,12 +462,17 @@
   va_end(va);
 }
 
+static int dashi(void)
+{
+  return TT.options&FLAG_i;
+}
+
 static void syntax_err(char *s)
 {
 // TODO: script@line only for script not interactive.
   sherror_msg("syntax error: %s", s);
   toys.exitval = 2;
-  if (!(TT.options&FLAG_i)) xexit();
+  if (!dashi()) xexit();
 }
 
 void debug_show_fds()
@@ -1384,6 +1406,17 @@
     ff->pp->urd = 0;
     free_process(ff->pp);
   }
+
+  // Unblock signal we just finished handling
+  if (TT.ff->signal) {
+    sigset_t set;
+
+    sigemptyset(&set);
+    sigaddset(&set, TT.ff->signal>>8);
+    sigprocmask(SIG_UNBLOCK, &set, 0);
+    toys.exitval = TT.ff->signal&255;
+  }
+
   free(dlist_pop(&TT.ff));
 }
 
@@ -2754,6 +2787,50 @@
   return pp;
 }
 
+// Handler called with all signals blocked, so no special locking needed.
+static void sig_fcall(int sig, siginfo_t *info, void *ucontext)
+{
+  // Tell run_lines() to eval trap, keep signal blocked until trap func ends
+  dlist_add(&TT.nextsig, (void *)(long)sig);
+  sigaddset(&((ucontext_t *)ucontext)->uc_sigmask, sig);
+}
+
+// Set signal handler to exec string, or reset to default if NULL
+static void signify(int sig, char *throw)
+{
+  void *ign = (sig==SIGPIPE || (sig==SIGINT && dashi())) ? SIG_IGN : SIG_DFL;
+  struct sigaction act = {0};
+  struct sh_fcall *ff;
+
+  if (throw && !*throw) throw = 0, ign = SIG_IGN;
+
+  // If we're replacing a running trap handler, garbe collect in fcall pop.
+  for (ff = TT.ff; ff && ff!=TT.ff->prev; ff = ff->next) {
+    if (ff->signal>>8==sig) {
+      push_arg(&ff->delete, TT.traps[sig]);
+      TT.traps[sig] = 0;
+      break;
+    }
+  }
+  free(TT.traps[sig]);
+  TT.traps[sig] = throw;
+
+  // Set signal handler (not for synthetic signals like EXIT)
+  if (sig && sig<NSIG) {
+    if (!TT.traps[sig]) {
+      act.sa_handler = ign;
+      act.sa_flags = SA_RESTART;
+    } else {
+      sigfillset(&act.sa_mask);
+      act.sa_flags = SA_SIGINFO;
+      act.sa_sigaction = sig_fcall;
+    }
+    sigaction(sig, &act, 0);
+  }
+}
+
+
+
 // Call binary, or run script via xexec("sh --")
 static void sh_exec(char **argv)
 {
@@ -2763,7 +2840,7 @@
   struct string_list *sl = 0;
   struct toy_list *tl = 0;
 
-  if (getpid() != TT.pid) signal(SIGINT, SIG_DFL); // TODO: restore all?
+  if (getpid() != TT.pid) signify(SIGINT, 0); // TODO: restore all?
   errno = ENOENT;
   if (strchr(ss, '/')) {
     if (access(ss, X_OK)) ss = 0;
@@ -2829,7 +2906,8 @@
 {
   char *s, *ss, *sss;
   struct sh_arg *arg = TT.ff->pl->arg;
-  int envlen, skiplen, funk = TT.funcslen, ii, jj, prefix = 0;
+  int envlen, skiplen, funk = TT.funcslen, ii, jj, prefix = 0,
+      pipe = TT.ff->blk->pipe;
   struct sh_process *pp;
 
   // Count leading variable assignments
@@ -2859,19 +2937,19 @@
 // TODO: [[ ~ ] expands but ((~)) doesn't, what else?
         if (expand_arg(&pp->arg, arg->v[envlen+ii], NO_PATH|NO_SPLIT, &pp->delete))
           break;
-      if (ii != skiplen) pp->exit = toys.exitval = 1;
+      if (ii!=skiplen) pp->exit = toys.exitval = 1;
     }
     if (pp->exit) return pp;
+  }
 
   // Are we calling a shell function?  TODO binary search
-  } else if (pp->arg.c)
-    if (!strchr(s, '/')) for (funk = 0; funk<TT.funcslen; funk++)
-       if (!strcmp(s, TT.functions[funk]->name)) break;
+  if (pp->arg.c && !strchr(s, '/')) for (funk = 0; funk<TT.funcslen; funk++)
+    if (!strcmp(s, TT.functions[funk]->name)) break;
 
   // If calling a function, or prefix assignment, or output is piped,
   // create new function context to hold local vars
+  prefix = (envlen && pp->arg.c) || pipe;
   (call_function()->pp = pp)->refcount++;
-  if (funk!=TT.funcslen || (envlen && pp->arg.c) || TT.ff->blk->pipe) prefix++;
 // TODO function needs to run asynchronously in pipeline, and backgrounded
 
   // perform any assignments
@@ -2887,39 +2965,35 @@
     } else pp->exit = 1;
   }
 
-  // Do the thing
-  if (pp->exit) s = 0; // leave $_ alone
-  else if (!pp->arg.c || envlen==arg->c) s = ""; // nothing to do but blank $_
-
-// TODO: call functions() FUNCTION
 // TODO what about "echo | x=1 | export fruit", must subshell? Test this.
 //   Several NOFORK can just NOP in a pipeline? Except ${a?b} still errors
 
+  // If variable expansion or assignment errored, do nothing
+  if (pp->exit);
+  // If nothing to do after assignments, blank $_
+  else if (!pp->arg.c) TT.ff->_ = "";
   // ((math))
-  else if (!smemcmp(s = *pp->arg.v, "((", 2)) {
+  else if (skiplen && !smemcmp(s = *pp->arg.v, "((", 2)) {
     char *ss = s+2;
     long long ll;
 
-    funk = TT.funcslen;
     ii = strlen(s)-2;
     if (!recalculate(&ll, &ss, 0) || ss!=s+ii)
       sherror_msg("bad math: %.*s @ %ld", ii-2, s+2, (long)(ss-s)-2);
     else toys.exitval = !ll;
     pp->exit = toys.exitval;
-    s = 0; // Really!
-
   // call shell function
   } else if (funk != TT.funcslen) {
-    s = 0; // $_ set on return, not here
     (TT.ff->function = TT.functions[funk])->refcount++;
     TT.ff->pl = TT.ff->function->pipeline;
     TT.ff->arg = pp->arg;
+    TT.ff->_ = pp->arg.v[pp->arg.c-1];
   // call command from $PATH or toybox builtin
   } else {
     struct toy_list *tl = toy_find(*pp->arg.v);
 
     jj = tl ? tl->flags : 0;
-    s = pp->arg.v[pp->arg.c-1];
+    TT.ff->_ = pp->arg.v[pp->arg.c-1];
 //dprintf(2, "%d run command %p %s\n", getpid(), TT.ff, *pp->arg.v); debug_show_fds();
 // TODO: figure out when can exec instead of forking, ala sh -c blah
 
@@ -2954,12 +3028,8 @@
         perror_msg("%s: vfork", *pp->arg.v);
   }
 
-  // cleanup
-  // TODO test "_=hello echo thing" sequencing: parent is updated despite local
-  if (!TT.ff->source && !TT.ff->pl) {
-    if (s && !TT.ff->_) TT.ff->_ = s;
-    end_fcall();
-  }
+  // pop the new function context if nothing left for it to do
+  if (!TT.ff->source && !TT.ff->pl) end_fcall();
 
   return pp;
 }
@@ -3505,7 +3575,7 @@
 // Wait for pid to exit and remove from jobs table, returning process or 0.
 struct sh_process *wait_job(int pid, int nohang)
 {
-  struct sh_process *pp = pp;
+  struct sh_process *pp QUIET;
   int ii, status, minus, plus;
 
   if (TT.jobs.c<1) return 0;
@@ -3546,7 +3616,7 @@
     rc = (pp->flags&PFLAG_NOT) ? !pp->exit : pp->exit;
   }
 
-  while ((pp = wait_job(-1, 1)) && (TT.options&FLAG_i)) {
+  while ((pp = wait_job(-1, 1)) && dashi()) {
     char *s = show_job(pp, pp->dash);
 
     dprintf(2, "%s\n", s);
@@ -3624,7 +3694,7 @@
   unsigned uu;
 
   if (!fp) return 0;
-  if (prompt>2 || (fp==stdin && (TT.options&FLAG_i))) {
+  if (prompt>2 || (fp==stdin && dashi())) {
     char ps[16];
 
     sprintf(ps, "PS%d", prompt);
@@ -3694,11 +3764,27 @@
 
   // iterate through pipeline segments
   for (;;) {
+    // Call functions for pending signals, in order received
+    while (TT.nextsig) {
+      struct double_list *dl;
+      sigset_t set;
+
+      // Block signals so list doesn't change under us
+      sigemptyset(&set);
+      sigprocmask(SIG_SETMASK, &set, &set);
+      dl = dlist_pop(&TT.nextsig);
+      sigprocmask(SIG_SETMASK, &set, 0);
+      ss = TT.traps[call_function()->signal = (long)dl->data];
+      TT.ff->signal = (TT.ff->signal<<8)|(toys.exitval&255);
+      free(dl);
+      TT.ff->source = fmemopen(ss, strlen(ss), "r");
+    }
     if (!TT.ff->pl) {
       if (TT.ff->source) break;
+      i = TT.ff->signal;
       end_fcall();
 // TODO can we move advance logic to start of loop to avoid straddle?
-      goto advance;
+      if (!i || !TT.ff || !TT.ff->pl) goto advance;
     }
 
     ctl = TT.ff->pl->end->arg->v[TT.ff->pl->end->arg->c];
@@ -4017,7 +4103,7 @@
         if (!TT.jobs.c) TT.jobcnt = 0;
         pplist->job = ++TT.jobcnt;
         arg_add(&TT.jobs, (void *)pplist);
-        if (TT.options&FLAG_i) dprintf(2, "[%u] %u\n", pplist->job,pplist->pid);
+        if (dashi()) dprintf(2, "[%u] %u\n", pplist->job,pplist->pid);
       } else {
         toys.exitval = wait_pipeline(pplist);
         llist_traverse(pplist, (void *)free_process);
@@ -4241,16 +4327,14 @@
   else {
     char buf[16];
 
-    sprintf(buf, "%u", atoi(ss+6)+1);
+    sprintf(buf, "%u", atoi(ss)+1);
     setvarval("SHLVL", buf)->flags |= VAR_EXPORT;
   }
-  if (TT.options&FLAG_i) {
-    if (!getvar("PS1")) setvarval("PS1", "$ "); // "\\s-\\v$ "
-    // TODO Set up signal handlers and grab control of this tty.
-    // ^C SIGINT ^\ SIGQUIT ^Z SIGTSTP SIGTTIN SIGTTOU SIGCHLD
-    // setsid(), setpgid(), tcsetpgrp()...
-    xsignal(SIGINT, SIG_IGN);
-  }
+  if (dashi() && !getvar("PS1")) setvarval("PS1", "$ "); // "\\s-\\v$ "
+  // TODO Set up signal handlers and grab control of this tty.
+  // ^C SIGINT ^\ SIGQUIT ^Z SIGTSTP SIGTTIN SIGTTOU SIGCHLD
+  // setsid(), setpgid(), tcsetpgrp()...
+  signify(SIGINT, 0);
 
   // Add additional input sources (in reverse order so they pop off stack right)
 
@@ -4270,7 +4354,7 @@
 
 //dprintf(2, "%d main", getpid()); for (unsigned uu = 0; toys.argv[uu]; uu++) dprintf(2, " %s", toys.argv[uu]); dprintf(2, "\n");
 
-  signal(SIGPIPE, SIG_IGN);
+  signify(SIGPIPE, 0);
   TT.options = OPT_B;
   TT.pid = getpid();
   srandom(TT.SECONDS = millitime());
@@ -4514,6 +4598,41 @@
   }
 }
 
+#define FOR_trap
+#include "generated/flags.h"
+
+void trap_main(void)
+{
+  int ii, jj;
+  char *sig = *toys.optargs;
+  struct signame sn[] = {{0, "EXIT"}, {NSIG, "DEBUG"}, {NSIG+1, "RETURN"}};
+
+  // Display data when asked
+  if (FLAG(l)) return list_signals();
+  else if (FLAG(p) || !toys.optc) {
+    for (ii = 0; ii<NSIG+2; ii++) if (TT.traps[ii]) {
+      if (!(sig = num_to_sig(ii))) for (jj = 0; jj<ARRAY_LEN(sn); jj++)
+        if (ii==sn[jj].num) sig = sn[jj].name;
+      if (sig) printf("trap -- '%s' %s\n", TT.traps[ii], sig); // TODO $'' esc
+    }
+    return;
+  }
+
+  // Assign new handler to each listed signal
+  if (toys.optc==1 || !**toys.optargs || !strcmp(*toys.optargs, "-")) sig = 0;
+  for (ii = toys.optc>1; toys.optargs[ii]; ii++) {
+    if (1>(jj = sig_to_num(toys.optargs[ii]))) {
+      while (++jj<ARRAY_LEN(sn))
+        if (!strcasecmp(toys.optargs[ii], sn[jj].name)) break;
+      if (jj==ARRAY_LEN(sn)) {
+        sherror_msg("%s: bad signal", toys.optargs[ii]);
+        continue;
+      } else jj = sn[jj].num;
+    }
+    signify(jj, (sig && *sig) ? xstrdup(sig) : sig);
+  }
+}
+
 // TODO need test: unset clears var first and stops, function only if no var.
 #define FOR_unset
 #include "generated/flags.h"
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index 87dc1af..0fc81a8 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -51,7 +51,7 @@
 // the default values are different but the flags are in the same order.
 USE_TOP(NEWTOY(top, ">0O*h" "Hk*o*p*u*s#<1d%<100=3000m#n#<1bq[!oO]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_IOTOP(NEWTOY(iotop, ">0AaKO" "Hk*o*p*u*s#<1=7d%<100=3000m#n#<1bq", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PGREP(NEWTOY(pgrep, "acld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_PKILL(NEWTOY(pkill,    "?Vu*U*t*s*P*g*G*fnovxl:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config PS
@@ -142,11 +142,12 @@
   bool "pgrep"
   default y
   help
-    usage: pgrep [-clfnovx] [-d DELIM] [-L SIGNAL] [PATTERN] [-G GID,] [-g PGRP,] [-P PPID,] [-s SID,] [-t TERM,] [-U UID,] [-u EUID,]
+    usage: pgrep [-aclfnovx] [-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.
 
+    -a	Show the full command line
     -c	Show only count of matches
     -d	Use DELIM instead of newline
     -L	Send SIGNAL instead of printing name
@@ -1902,7 +1903,7 @@
   }
   if (!FLAG(c) && (!TT.pgrep.signal || TT.tty)) {
     printf("%lld", *tb->slot);
-    if (FLAG(l)) printf(" %s", tb->str+tb->offset[4]*FLAG(f));
+    if (FLAG(a)|FLAG(l)) printf(" %s", tb->str+tb->offset[4]*FLAG(a));
     printf("%s", TT.pgrep.d ? TT.pgrep.d : "\n");
   }
 }
@@ -1971,7 +1972,7 @@
       !(toys.optflags&(FLAG_G|FLAG_g|FLAG_P|FLAG_s|FLAG_t|FLAG_U|FLAG_u)))
     if (!toys.optc) help_exit("No PATTERN");
 
-  if (FLAG(f)) TT.bits |= _PS_CMDLINE;
+  if (FLAG(f)|FLAG(a)) TT.bits |= _PS_CMDLINE;
   for (arg = toys.optargs; *arg; arg++) {
     reg = xmalloc(sizeof(struct regex_list));
     xregcomp(&reg->reg, *arg, REG_EXTENDED);
diff --git a/www/header.html b/www/header.html
index 76dd2d8..e91265e 100644
--- a/www/header.html
+++ b/www/header.html
@@ -30,7 +30,7 @@
       </ul>
     </li>
     <li><a href="downloads">Source tarballs</a></li>
-    <li><a href="bin">Binaries</a></li>
+    <li><a href="/bin">Binaries</a></li>
     <li><a href="downloads/binaries/mkroot/latest">System Images</a></li>
     <li><a href="downloads/binaries/toolchains/latest">Compilers</a></li>
   </ul>