#include "strutils.h"
#include "ttyutils.h"
#include "pager.h"
+#include "env.h"
static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
pager_caught_sigpipe = 0;
}
+/* Decide whether the pager should run for the given @mode.
+ *
+ * UL_PAGER_ALWAYS and UL_PAGER_NEVER reflect an explicit user choice
+ * (--pager / --nopager) and are honored unconditionally.
+ *
+ * UL_PAGER_AUTO consults the PAGER_ENABLE environment variable (accepted
+ * values parsed by ul_strtobool()). PAGER_ENABLE is ignored when stdout
+ * is not a terminal, so pipelines like `lslocks | grep foo` do not spawn
+ * a pager. The variable is also suppressed in privileged (SUID/SGID)
+ * contexts via safe_getenv().
+ */
+bool pager_is_enabled(enum ul_pagermode mode)
+{
+ switch (mode) {
+ case UL_PAGER_ALWAYS:
+ return true;
+ case UL_PAGER_NEVER:
+ return false;
+ case UL_PAGER_AUTO: {
+ const char *s;
+ bool val;
+
+ if (!isatty(STDOUT_FILENO))
+ return false;
+ s = safe_getenv("PAGER_ENABLE");
+ if (!s || ul_strtobool(s, &val) != 0)
+ return false;
+ return val;
+ }
+ default:
+ return false;
+ }
+}
+
#ifdef TEST_PROGRAM_PAGER
#define MAX 255
lslocks --filter 'TYPE != "POSIX" and MODE == "READ" and PATH =~ ".*\.qcow2"'
____
+*--pager*::
+Pipe output into a pager (by default *less*(1)). The pager freezes the
+header line so column names stay visible while scrolling.
+The *PAGER* environment variable overrides the default pager program.
+Mutually exclusive with *--json* and *--raw*.
+
+*--nopager*::
+Do not pipe output into a pager. Overrides the *PAGER_ENABLE* environment
+variable.
+
*-r*, *--raw*::
Use the raw output format.
*LSLOCKS_COLUMNS*=::
Specify a comma-separated list of output columns to print. All columns listed by *--list-columns* can be used.
+*PAGER_ENABLE*=::
+If set to a recognized boolean value (e.g. "yes", "true", "on", "1"), automatically pipe output through a pager.
+The *--pager* and *--nopager* command-line options override this variable.
+Ignored when standard output is not a terminal, and in privileged (setuid/setgid) contexts.
+This is a project-independent variable; other tools may support it as well.
+
== OUTPUT
COMMAND::
#include "procfs.h"
#include "column-list-table.h"
#include "fileutils.h"
+#include "pager.h"
/* column IDs */
enum {
int raw;
int json;
int bytes;
+ enum ul_pagermode pager_mode;
pid_t target_pid;
fputs(_(" -Q, --filter <expr> apply display filter\n"), out);
fputs(_(" -r, --raw use the raw output format\n"), out);
fputs(_(" -u, --notruncate don't truncate text in columns\n"), out);
+ fputs(_(" --pager pipe output into a pager\n"), out);
+ fputs(_(" --nopager disable pager output\n"), out);
fputs(USAGE_SEPARATOR, out);
fprintf(out, USAGE_LIST_COLUMNS_OPTION(24));
struct libscols_filter *filter = NULL;
char *outarg = NULL;
enum {
- OPT_OUTPUT_ALL = CHAR_MAX + 1
+ OPT_OUTPUT_ALL = CHAR_MAX + 1,
+ OPT_PAGER,
+ OPT_NO_PAGER,
};
static const struct option long_opts[] = {
{ "bytes", no_argument, NULL, 'b' },
{ "noinaccessible", no_argument, NULL, 'i' },
{ "filter", required_argument, NULL, 'Q' },
{ "list-columns", no_argument, NULL, 'H' },
+ { "pager", no_argument, NULL, OPT_PAGER },
+ { "nopager", no_argument, NULL, OPT_NO_PAGER },
{ NULL, 0, NULL, 0 }
};
static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
{ 'J','r' },
+ { 'J', OPT_PAGER },
+ { 'r', OPT_PAGER },
+ { OPT_PAGER, OPT_NO_PAGER },
{ 0 }
};
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
break;
case 'J':
lslocks.json = 1;
+ lslocks.pager_mode = UL_PAGER_NEVER;
break;
case 'p':
lslocks.target_pid = strtopid_or_err(optarg, _("invalid PID argument"));
break;
case 'r':
lslocks.raw = 1;
+ lslocks.pager_mode = UL_PAGER_NEVER;
break;
case 'u':
disable_columns_truncate();
case 'H':
collist = 1;
break;
+ case OPT_PAGER:
+ lslocks.pager_mode = UL_PAGER_ALWAYS;
+ break;
+ case OPT_NO_PAGER:
+ lslocks.pager_mode = UL_PAGER_NEVER;
+ break;
case 'Q':
filter = new_filter(optarg);
break;
if (filter)
init_scols_filter(table, filter, lslocks.bytes);
+ if (pager_is_enabled(lslocks.pager_mode))
+ pager_open_header(lslocks.no_headings ? 0 : 1, 0);
+
/* get_pids_locks() get locks related information from "lock:" fields
* of /proc/$pid/fdinfo/$fd as fallback information.
* get_proc_locks() used the fallback information if /proc/locks
scols_unref_table(table);
lslocks_free(&lslocks);
+
+ pager_close();
return rc;
}