Rebase to 4.0.2
New version and name of libproc is introduced. The library is completely rewritten and different from procps-ng-3.*. All dependencies on procps-ng-devel must align with this change.
This commit is contained in:
parent
4a987965c3
commit
0c887b157e
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,6 +1 @@
|
||||
/procps-ng-3.3.12.tar.xz
|
||||
/procps-ng-3.3.13.tar.xz
|
||||
/procps-ng-3.3.14.tar.xz
|
||||
/procps-ng-3.3.15.tar.xz
|
||||
/procps-ng-3.3.16.tar.xz
|
||||
/procps-ng-3.3.17.tar.xz
|
||||
/procps-ng-4.0.2.tar.xz
|
||||
|
@ -1,49 +0,0 @@
|
||||
diff --git a/lib/test_process.c b/lib/test_process.c
|
||||
index e20b270d..f8ff5ed0 100644
|
||||
--- a/lib/test_process.c
|
||||
+++ b/lib/test_process.c
|
||||
@@ -69,6 +69,7 @@ signal_handler(int signum, siginfo_t *siginfo, void *ucontext)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
+ free(signame);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
diff --git a/pmap.c b/pmap.c
|
||||
index 49a2a6a8..d8565fc3 100644
|
||||
--- a/pmap.c
|
||||
+++ b/pmap.c
|
||||
@@ -346,6 +346,9 @@ static void print_extended_maps (FILE *f)
|
||||
if (listnode == NULL) {
|
||||
assert(firstmapping == 2);
|
||||
listnode = calloc(1, sizeof *listnode);
|
||||
+ if (listnode == NULL)
|
||||
+ xerrx(EXIT_FAILURE, _("ERROR: memory allocation failed"));
|
||||
+
|
||||
if (listhead == NULL) {
|
||||
assert(listtail == NULL);
|
||||
listhead = listnode;
|
||||
diff --git a/watch.c b/watch.c
|
||||
index 1a95454e..772879cd 100644
|
||||
--- a/watch.c
|
||||
+++ b/watch.c
|
||||
@@ -124,8 +124,6 @@ static void reset_ansi(void)
|
||||
|
||||
static void init_ansi_colors(void)
|
||||
{
|
||||
- int color;
|
||||
-
|
||||
short ncurses_colors[] = {
|
||||
-1, COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW,
|
||||
COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
|
||||
@@ -172,6 +170,9 @@ static int process_ansi_color_escape_sequence(char** escape_sequence) {
|
||||
// ESC[ 48;2;⟨r⟩;⟨g⟩;⟨b⟩ m Select RGB background color
|
||||
int num;
|
||||
|
||||
+ if (!escape_sequence)
|
||||
+ return 0; /* avoid NULLPTR dereference, return "not understood" */
|
||||
+
|
||||
if ((*escape_sequence)[0] != ';')
|
||||
return 0; /* not understood */
|
||||
|
@ -1,12 +0,0 @@
|
||||
diff -up ./free.c.ori ./free.c
|
||||
--- ./free.c.ori 2022-09-20 15:02:22.469320938 +0200
|
||||
+++ ./free.c 2022-09-20 15:03:33.767710892 +0200
|
||||
@@ -120,7 +120,7 @@ static const char *scale_size(unsigned l
|
||||
|
||||
/* default output */
|
||||
if (args.exponent == 0 && !(flags & FREE_HUMANREADABLE)) {
|
||||
- snprintf(buf, sizeof(buf), "%ld", size);
|
||||
+ snprintf(buf, sizeof(buf), "%ld", (long)( ((long long int)size) * 1024 / (long long int)base));
|
||||
return buf;
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
diff --git a/pidof.c b/pidof.c
|
||||
index b0d08cc..90ecb13 100644
|
||||
--- a/pidof.c
|
||||
+++ b/pidof.c
|
||||
@@ -142,6 +142,7 @@ static void select_procs (void)
|
||||
static int size = 0;
|
||||
char *cmd_arg0, *cmd_arg0base;
|
||||
char *cmd_arg1, *cmd_arg1base;
|
||||
+ char *stat_cmd;
|
||||
char *program_base;
|
||||
char *root_link;
|
||||
char *exe_link;
|
||||
@@ -167,9 +168,10 @@ static void select_procs (void)
|
||||
}
|
||||
}
|
||||
|
||||
- if (!is_omitted(task.XXXID) && task.cmdline && *task.cmdline) {
|
||||
+ if (!is_omitted(task.XXXID)) {
|
||||
|
||||
- cmd_arg0 = *task.cmdline;
|
||||
+ cmd_arg0 = (task.cmdline && *task.cmdline) ? *task.cmdline : "\0";
|
||||
+ stat_cmd = task.cmd ? task.cmd : "\0";
|
||||
|
||||
/* processes starting with '-' are login shells */
|
||||
if (*cmd_arg0 == '-') {
|
||||
@@ -191,12 +193,14 @@ static void select_procs (void)
|
||||
!strcmp(program_base, cmd_arg0) ||
|
||||
!strcmp(program, cmd_arg0) ||
|
||||
|
||||
+ !strcmp(program, stat_cmd) ||
|
||||
+
|
||||
!strcmp(program, exe_link_base) ||
|
||||
!strcmp(program, exe_link))
|
||||
{
|
||||
match = 1;
|
||||
|
||||
- } else if (opt_scripts_too && *(task.cmdline+1)) {
|
||||
+ } else if (opt_scripts_too && task.cmdline && *(task.cmdline+1)) {
|
||||
|
||||
cmd_arg1 = *(task.cmdline+1);
|
||||
|
@ -1,99 +0,0 @@
|
||||
diff --git a/pidof.1 b/pidof.1
|
||||
index 8ef4abf..5f95b85 100644
|
||||
--- a/pidof.1
|
||||
+++ b/pidof.1
|
||||
@@ -45,6 +45,9 @@ the current root directory of processes they do not own.
|
||||
.IP \-x
|
||||
Scripts too - this causes the program to also return process id's of
|
||||
shells running the named scripts.
|
||||
+.IP \-w
|
||||
+Show also processes that do not have visible command line (e.g. kernel
|
||||
+worker threads).
|
||||
.IP "-o \fIomitpid\fP"
|
||||
Tells \fIpidof\fP to omit processes with that process id. The special
|
||||
pid \fB%PPID\fP can be used to name the parent process of the \fIpidof\fP
|
||||
diff --git a/pidof.c b/pidof.c
|
||||
index 90ecb13..0754754 100644
|
||||
--- a/pidof.c
|
||||
+++ b/pidof.c
|
||||
@@ -55,6 +55,8 @@ static char *program = NULL;
|
||||
static int opt_single_shot = 0; /* -s */
|
||||
static int opt_scripts_too = 0; /* -x */
|
||||
static int opt_rootdir_check = 0; /* -c */
|
||||
+static int opt_with_workers = 0; /* -w */
|
||||
+
|
||||
|
||||
static char *pidof_root = NULL;
|
||||
|
||||
@@ -69,6 +71,7 @@ static int __attribute__ ((__noreturn__)) usage(int opt)
|
||||
fputs(_(" -s, --single-shot return one PID only\n"), fp);
|
||||
fputs(_(" -c, --check-root omit processes with different root\n"), fp);
|
||||
fputs(_(" -x also find shells running the named scripts\n"), fp);
|
||||
+ fputs(_(" -w, --with-workers show kernel workers too\n"), fp);
|
||||
fputs(_(" -o, --omit-pid <PID,...> omit processes with PID\n"), fp);
|
||||
fputs(_(" -S, --separator SEP use SEP as separator put between PIDs"), fp);
|
||||
fputs(USAGE_SEPARATOR, fp);
|
||||
@@ -142,7 +145,6 @@ static void select_procs (void)
|
||||
static int size = 0;
|
||||
char *cmd_arg0, *cmd_arg0base;
|
||||
char *cmd_arg1, *cmd_arg1base;
|
||||
- char *stat_cmd;
|
||||
char *program_base;
|
||||
char *root_link;
|
||||
char *exe_link;
|
||||
@@ -168,10 +170,9 @@ static void select_procs (void)
|
||||
}
|
||||
}
|
||||
|
||||
- if (!is_omitted(task.XXXID)) {
|
||||
+ if (!is_omitted(task.XXXID) && ((task.cmdline && *task.cmdline) || opt_with_workers)) {
|
||||
|
||||
cmd_arg0 = (task.cmdline && *task.cmdline) ? *task.cmdline : "\0";
|
||||
- stat_cmd = task.cmd ? task.cmd : "\0";
|
||||
|
||||
/* processes starting with '-' are login shells */
|
||||
if (*cmd_arg0 == '-') {
|
||||
@@ -193,7 +194,7 @@ static void select_procs (void)
|
||||
!strcmp(program_base, cmd_arg0) ||
|
||||
!strcmp(program, cmd_arg0) ||
|
||||
|
||||
- !strcmp(program, stat_cmd) ||
|
||||
+ (opt_with_workers && !strcmp(program, task.cmd)) ||
|
||||
|
||||
!strcmp(program, exe_link_base) ||
|
||||
!strcmp(program, exe_link))
|
||||
@@ -293,13 +294,14 @@ int main (int argc, char **argv)
|
||||
int first_pid = 1;
|
||||
|
||||
const char *separator = " ";
|
||||
- const char *opts = "scdnxmo:S:?Vh";
|
||||
+ const char *opts = "scdnxwmo:S:?Vh";
|
||||
|
||||
static const struct option longopts[] = {
|
||||
{"check-root", no_argument, NULL, 'c'},
|
||||
{"single-shot", no_argument, NULL, 's'},
|
||||
{"omit-pid", required_argument, NULL, 'o'},
|
||||
{"separator", required_argument, NULL, 'S'},
|
||||
+ {"with-workers", no_argument, NULL, 'w'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"version", no_argument, NULL, 'V'},
|
||||
{NULL, 0, NULL, 0}
|
||||
@@ -325,6 +327,9 @@ int main (int argc, char **argv)
|
||||
case 'x':
|
||||
opt_scripts_too = 1;
|
||||
break;
|
||||
+ case 'w':
|
||||
+ opt_with_workers = 1;
|
||||
+ break;
|
||||
case 'c':
|
||||
if (geteuid() == 0) {
|
||||
opt_rootdir_check = 1;
|
||||
@@ -359,6 +364,8 @@ int main (int argc, char **argv)
|
||||
|
||||
program = argv[optind++];
|
||||
|
||||
+ if (*program == '\0') continue;
|
||||
+
|
||||
select_procs(); /* get the list of matching processes */
|
||||
|
||||
if (proc_count) {
|
@ -1,22 +0,0 @@
|
||||
commit 584c65ba375a4f7242ddeb74f6006f8f9f5c8d08
|
||||
Author: Jan Rybar <jrybar@redhat.com>
|
||||
Date: Fri Nov 6 14:45:56 2020 +0000
|
||||
|
||||
pkill manpage to document '-e' option
|
||||
|
||||
diff --git a/pgrep.1 b/pgrep.1
|
||||
index 9c29fb9c..a1810f0d 100644
|
||||
--- a/pgrep.1
|
||||
+++ b/pgrep.1
|
||||
@@ -62,6 +62,11 @@ newline).
|
||||
.RB ( pgrep
|
||||
only.)
|
||||
.TP
|
||||
+\fB\-e\fR, \fB\-\-echo\fR
|
||||
+Display name and PID of the process being killed.
|
||||
+.RB ( pkill
|
||||
+only.)
|
||||
+.TP
|
||||
\fB\-f\fR, \fB\-\-full\fR
|
||||
The
|
||||
.I pattern
|
@ -1,61 +0,0 @@
|
||||
diff -up ./ps/output.c.ori ./ps/output.c
|
||||
--- ./ps/output.c.ori 2016-07-09 23:49:25.825306872 +0200
|
||||
+++ ./ps/output.c 2018-02-26 15:09:38.291043349 +0100
|
||||
@@ -1201,6 +1201,34 @@ static int pr_sgi_p(char *restrict const
|
||||
return snprintf(outbuf, COLWID, "*");
|
||||
}
|
||||
|
||||
+/* LoginID implementation */
|
||||
+static int pr_luid(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
+ char filename[48];
|
||||
+ ssize_t num_read;
|
||||
+ int fd;
|
||||
+ u_int32_t luid;
|
||||
+
|
||||
+ snprintf(filename, sizeof filename, "/proc/%d/loginuid", pp->tgid);
|
||||
+
|
||||
+ if ((fd = open(filename, O_RDONLY, 0)) != -1) {
|
||||
+ num_read = read(fd, outbuf, OUTBUF_SIZE - 1);
|
||||
+ close(fd);
|
||||
+ if (num_read > 0) {
|
||||
+ outbuf[num_read] = '\0';
|
||||
+
|
||||
+ // processes born before audit have no LoginID set
|
||||
+ luid = (u_int32_t) atoi(outbuf);
|
||||
+ if (luid != -1)
|
||||
+ return num_read;
|
||||
+ }
|
||||
+ }
|
||||
+ outbuf[0] = '-';
|
||||
+ outbuf[1] = '\0';
|
||||
+ num_read = 1;
|
||||
+ return num_read;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/************************* Systemd stuff ********************************/
|
||||
static int pr_sd_unit(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
return snprintf(outbuf, COLWID, "%s", pp->sd_unit);
|
||||
@@ -1513,7 +1541,7 @@ static const format_struct format_array[
|
||||
{"longtname", "TTY", pr_tty8, sr_tty, 8, 0, DEC, PO|LEFT},
|
||||
{"lsession", "SESSION", pr_sd_session, sr_nop, 11, SD, LNX, ET|LEFT},
|
||||
{"lstart", "STARTED", pr_lstart, sr_nop, 24, 0, XXX, ET|RIGHT},
|
||||
-{"luid", "LUID", pr_nop, sr_nop, 5, 0, LNX, ET|RIGHT}, /* login ID */
|
||||
+{"luid", "LUID", pr_luid, sr_nop, 5, 0, LNX, ET|RIGHT}, /* login ID */
|
||||
{"luser", "LUSER", pr_nop, sr_nop, 8, USR, LNX, ET|USER}, /* login USER */
|
||||
{"lwp", "LWP", pr_tasks, sr_tasks, 5, 0, SUN, TO|PIDMAX|RIGHT},
|
||||
{"lxc", "LXC", pr_lxcname, sr_lxcname, 8, LXC, LNX, ET|LEFT},
|
||||
diff -up ./ps/ps.1.ori ./ps/ps.1
|
||||
--- ./ps/ps.1.ori 2016-05-07 13:15:32.014390172 +0200
|
||||
+++ ./ps/ps.1 2018-02-26 15:09:38.292043345 +0100
|
||||
@@ -1322,6 +1322,10 @@ displays the login session identifier of
|
||||
if systemd support has been included.
|
||||
T}
|
||||
|
||||
+luid LUID T{
|
||||
+displays Login ID associated with a process.
|
||||
+T}
|
||||
+
|
||||
lwp LWP T{
|
||||
light weight process (thread) ID of the dispatchable entity (alias
|
||||
.BR spid , \ tid ).
|
@ -1,11 +0,0 @@
|
||||
diff -up ./procio.c.ori ./procio.c
|
||||
--- ./procio.c.ori 2018-04-05 13:16:16.926741440 +0200
|
||||
+++ ./procio.c 2018-04-05 13:16:31.076685287 +0200
|
||||
@@ -24,7 +24,6 @@
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
-#include <libio.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
@ -1,337 +0,0 @@
|
||||
From 9d2ec74b76d220f5343e548fcb7058d723293a22 Mon Sep 17 00:00:00 2001
|
||||
From: Qualys Security Advisory <qsa@qualys.com>
|
||||
Date: Thu, 1 Jan 1970 00:00:00 +0000
|
||||
Subject: [PATCH 1/3] proc/alloc.*: Use size_t, not unsigned int.
|
||||
|
||||
Otherwise this can truncate sizes on 64-bit platforms, and is one of the
|
||||
reasons the integer overflows in file2strvec() are exploitable at all.
|
||||
Also: catch potential integer overflow in xstrdup() (should never
|
||||
happen, but better safe than sorry), and use memcpy() instead of
|
||||
strcpy() (faster).
|
||||
|
||||
Warnings:
|
||||
|
||||
- in glibc, realloc(ptr, 0) is equivalent to free(ptr), but not here,
|
||||
because of the ++size;
|
||||
|
||||
- here, xstrdup() can return NULL (if str is NULL), which goes against
|
||||
the idea of the xalloc wrappers.
|
||||
|
||||
We were tempted to call exit() or xerrx() in those cases, but decided
|
||||
against it, because it might break things in unexpected places; TODO?
|
||||
---
|
||||
proc/alloc.c | 20 ++++++++++++--------
|
||||
proc/alloc.h | 4 ++--
|
||||
2 files changed, 14 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/proc/alloc.c b/proc/alloc.c
|
||||
index 94af47f..1768d73 100644
|
||||
--- a/proc/alloc.c
|
||||
+++ b/proc/alloc.c
|
||||
@@ -37,14 +37,14 @@ static void xdefault_error(const char *restrict fmts, ...) {
|
||||
message_fn xalloc_err_handler = xdefault_error;
|
||||
|
||||
|
||||
-void *xcalloc(unsigned int size) {
|
||||
+void *xcalloc(size_t size) {
|
||||
void * p;
|
||||
|
||||
if (size == 0)
|
||||
++size;
|
||||
p = calloc(1, size);
|
||||
if (!p) {
|
||||
- xalloc_err_handler("%s failed to allocate %u bytes of memory", __func__, size);
|
||||
+ xalloc_err_handler("%s failed to allocate %zu bytes of memory", __func__, size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return p;
|
||||
@@ -57,20 +57,20 @@ void *xmalloc(size_t size) {
|
||||
++size;
|
||||
p = malloc(size);
|
||||
if (!p) {
|
||||
- xalloc_err_handler("%s failed to allocate %zu bytes of memory", __func__, size);
|
||||
+ xalloc_err_handler("%s failed to allocate %zu bytes of memory", __func__, size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
|
||||
-void *xrealloc(void *oldp, unsigned int size) {
|
||||
+void *xrealloc(void *oldp, size_t size) {
|
||||
void *p;
|
||||
|
||||
if (size == 0)
|
||||
++size;
|
||||
p = realloc(oldp, size);
|
||||
if (!p) {
|
||||
- xalloc_err_handler("%s failed to allocate %u bytes of memory", __func__, size);
|
||||
+ xalloc_err_handler("%s failed to allocate %zu bytes of memory", __func__, size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return(p);
|
||||
@@ -80,13 +80,17 @@ char *xstrdup(const char *str) {
|
||||
char *p = NULL;
|
||||
|
||||
if (str) {
|
||||
- unsigned int size = strlen(str) + 1;
|
||||
+ size_t size = strlen(str) + 1;
|
||||
+ if (size < 1) {
|
||||
+ xalloc_err_handler("%s refused to allocate %zu bytes of memory", __func__, size);
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
p = malloc(size);
|
||||
if (!p) {
|
||||
- xalloc_err_handler("%s failed to allocate %u bytes of memory", __func__, size);
|
||||
+ xalloc_err_handler("%s failed to allocate %zu bytes of memory", __func__, size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
- strcpy(p, str);
|
||||
+ memcpy(p, str, size);
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
diff --git a/proc/alloc.h b/proc/alloc.h
|
||||
index 19c91d7..6787a72 100644
|
||||
--- a/proc/alloc.h
|
||||
+++ b/proc/alloc.h
|
||||
@@ -10,9 +10,9 @@ typedef void (*message_fn)(const char *__restrict, ...) __attribute__((format(pr
|
||||
/* change xalloc_err_handler to override the default fprintf(stderr... */
|
||||
extern message_fn xalloc_err_handler;
|
||||
|
||||
-extern void *xcalloc(unsigned int size) MALLOC;
|
||||
+extern void *xcalloc(size_t size) MALLOC;
|
||||
extern void *xmalloc(size_t size) MALLOC;
|
||||
-extern void *xrealloc(void *oldp, unsigned int size) MALLOC;
|
||||
+extern void *xrealloc(void *oldp, size_t size) MALLOC;
|
||||
extern char *xstrdup(const char *str) MALLOC;
|
||||
|
||||
EXTERN_C_END
|
||||
--
|
||||
2.14.3
|
||||
|
||||
|
||||
From de660b14b80188d9b323c4999d1b91a9456ed687 Mon Sep 17 00:00:00 2001
|
||||
From: Qualys Security Advisory <qsa@qualys.com>
|
||||
Date: Thu, 1 Jan 1970 00:00:00 +0000
|
||||
Subject: [PATCH 2/3] proc/readproc.c: Harden file2str().
|
||||
|
||||
1/ Replace sprintf() with snprintf() (and check for truncation).
|
||||
|
||||
2/ Prevent an integer overflow of ub->siz. The "tot_read--" is needed to
|
||||
avoid an off-by-one overflow in "ub->buf[tot_read] = '\0'". It is safe
|
||||
to decrement tot_read here, because we know that tot_read is equal to
|
||||
ub->siz (and ub->siz is very large).
|
||||
|
||||
We believe that truncation is a better option than failure (implementing
|
||||
failure instead should be as easy as replacing the "tot_read--" with
|
||||
"tot_read = 0").
|
||||
---
|
||||
proc/readproc.c | 10 ++++++++--
|
||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/proc/readproc.c b/proc/readproc.c
|
||||
index 9e3afc9..39235c7 100644
|
||||
--- a/proc/readproc.c
|
||||
+++ b/proc/readproc.c
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
+#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef WITH_SYSTEMD
|
||||
@@ -635,7 +636,7 @@ static void statm2proc(const char* s, proc_t *restrict P) {
|
||||
static int file2str(const char *directory, const char *what, struct utlbuf_s *ub) {
|
||||
#define buffGRW 1024
|
||||
char path[PROCPATHLEN];
|
||||
- int fd, num, tot_read = 0;
|
||||
+ int fd, num, tot_read = 0, len;
|
||||
|
||||
/* on first use we preallocate a buffer of minimum size to emulate
|
||||
former 'local static' behavior -- even if this read fails, that
|
||||
@@ -643,11 +644,16 @@ static int file2str(const char *directory, const char *what, struct utlbuf_s *ub
|
||||
( besides, with this xcalloc we will never need to use memcpy ) */
|
||||
if (ub->buf) ub->buf[0] = '\0';
|
||||
else ub->buf = xcalloc((ub->siz = buffGRW));
|
||||
- sprintf(path, "%s/%s", directory, what);
|
||||
+ len = snprintf(path, sizeof path, "%s/%s", directory, what);
|
||||
+ if (len <= 0 || (size_t)len >= sizeof path) return -1;
|
||||
if (-1 == (fd = open(path, O_RDONLY, 0))) return -1;
|
||||
while (0 < (num = read(fd, ub->buf + tot_read, ub->siz - tot_read))) {
|
||||
tot_read += num;
|
||||
if (tot_read < ub->siz) break;
|
||||
+ if (ub->siz >= INT_MAX - buffGRW) {
|
||||
+ tot_read--;
|
||||
+ break;
|
||||
+ }
|
||||
ub->buf = xrealloc(ub->buf, (ub->siz += buffGRW));
|
||||
};
|
||||
ub->buf[tot_read] = '\0';
|
||||
--
|
||||
2.14.3
|
||||
|
||||
|
||||
From 44a4b658f45bc3fbd7170662a52038a7b35c83de Mon Sep 17 00:00:00 2001
|
||||
From: Qualys Security Advisory <qsa@qualys.com>
|
||||
Date: Thu, 1 Jan 1970 00:00:00 +0000
|
||||
Subject: [PATCH 3/3] proc/readproc.c: Fix bugs and overflows in file2strvec().
|
||||
|
||||
Note: this is by far the most important and complex patch of the whole
|
||||
series, please review it carefully; thank you very much!
|
||||
|
||||
For this patch, we decided to keep the original function's design and
|
||||
skeleton, to avoid regressions and behavior changes, while fixing the
|
||||
various bugs and overflows. And like the "Harden file2str()" patch, this
|
||||
patch does not fail when about to overflow, but truncates instead: there
|
||||
is information available about this process, so return it to the caller;
|
||||
also, we used INT_MAX as a limit, but a lower limit could be used.
|
||||
|
||||
The easy changes:
|
||||
|
||||
- Replace sprintf() with snprintf() (and check for truncation).
|
||||
|
||||
- Replace "if (n == 0 && rbuf == 0)" with "if (n <= 0 && tot <= 0)" and
|
||||
do break instead of return: it simplifies the code (only one place to
|
||||
handle errors), and also guarantees that in the while loop either n or
|
||||
tot is > 0 (or both), even if n is reset to 0 when about to overflow.
|
||||
|
||||
- Remove the "if (n < 0)" block in the while loop: it is (and was) dead
|
||||
code, since we enter the while loop only if n >= 0.
|
||||
|
||||
- Rewrite the missing-null-terminator detection: in the original
|
||||
function, if the size of the file is a multiple of 2047, a null-
|
||||
terminator is appended even if the file is already null-terminated.
|
||||
|
||||
- Replace "if (n <= 0 && !end_of_file)" with "if (n < 0 || tot <= 0)":
|
||||
originally, it was equivalent to "if (n < 0)", but we added "tot <= 0"
|
||||
to handle the first break of the while loop, and to guarantee that in
|
||||
the rest of the function tot is > 0.
|
||||
|
||||
- Double-force ("belt and suspenders") the null-termination of rbuf:
|
||||
this is (and was) essential to the correctness of the function.
|
||||
|
||||
- Replace the final "while" loop with a "for" loop that behaves just
|
||||
like the preceding "for" loop: in the original function, this would
|
||||
lead to unexpected results (for example, if rbuf is |\0|A|\0|, this
|
||||
would return the array {"",NULL} but should return {"","A",NULL}; and
|
||||
if rbuf is |A|\0|B| (should never happen because rbuf should be null-
|
||||
terminated), this would make room for two pointers in ret, but would
|
||||
write three pointers to ret).
|
||||
|
||||
The hard changes:
|
||||
|
||||
- Prevent the integer overflow of tot in the while loop, but unlike
|
||||
file2str(), file2strvec() cannot let tot grow until it almost reaches
|
||||
INT_MAX, because it needs more space for the pointers: this is why we
|
||||
introduced ARG_LEN, which also guarantees that we can add "align" and
|
||||
a few sizeof(char*)s to tot without overflowing.
|
||||
|
||||
- Prevent the integer overflow of "tot + c + align": when INT_MAX is
|
||||
(almost) reached, we write the maximal safe amount of pointers to ret
|
||||
(ARG_LEN guarantees that there is always space for *ret = rbuf and the
|
||||
NULL terminator).
|
||||
---
|
||||
proc/readproc.c | 53 ++++++++++++++++++++++++++++++++---------------------
|
||||
1 file changed, 32 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/proc/readproc.c b/proc/readproc.c
|
||||
index 39235c7..94ca4e9 100644
|
||||
--- a/proc/readproc.c
|
||||
+++ b/proc/readproc.c
|
||||
@@ -665,11 +665,12 @@ static int file2str(const char *directory, const char *what, struct utlbuf_s *ub
|
||||
|
||||
static char** file2strvec(const char* directory, const char* what) {
|
||||
char buf[2048]; /* read buf bytes at a time */
|
||||
- char *p, *rbuf = 0, *endbuf, **q, **ret;
|
||||
+ char *p, *rbuf = 0, *endbuf, **q, **ret, *strp;
|
||||
int fd, tot = 0, n, c, end_of_file = 0;
|
||||
int align;
|
||||
|
||||
- sprintf(buf, "%s/%s", directory, what);
|
||||
+ const int len = snprintf(buf, sizeof buf, "%s/%s", directory, what);
|
||||
+ if(len <= 0 || (size_t)len >= sizeof buf) return NULL;
|
||||
fd = open(buf, O_RDONLY, 0);
|
||||
if(fd==-1) return NULL;
|
||||
|
||||
@@ -677,18 +678,23 @@ static char** file2strvec(const char* directory, const char* what) {
|
||||
while ((n = read(fd, buf, sizeof buf - 1)) >= 0) {
|
||||
if (n < (int)(sizeof buf - 1))
|
||||
end_of_file = 1;
|
||||
- if (n == 0 && rbuf == 0) {
|
||||
- close(fd);
|
||||
- return NULL; /* process died between our open and read */
|
||||
+ if (n <= 0 && tot <= 0) { /* nothing read now, nothing read before */
|
||||
+ break; /* process died between our open and read */
|
||||
}
|
||||
- if (n < 0) {
|
||||
- if (rbuf)
|
||||
- free(rbuf);
|
||||
- close(fd);
|
||||
- return NULL; /* read error */
|
||||
+ /* ARG_LEN is our guesstimated median length of a command-line argument
|
||||
+ or environment variable (the minimum is 1, the maximum is 131072) */
|
||||
+ #define ARG_LEN 64
|
||||
+ if (tot >= INT_MAX / (ARG_LEN + (int)sizeof(char*)) * ARG_LEN - n) {
|
||||
+ end_of_file = 1; /* integer overflow: null-terminate and break */
|
||||
+ n = 0; /* but tot > 0 */
|
||||
}
|
||||
- if (end_of_file && (n == 0 || buf[n-1]))/* last read char not null */
|
||||
+ #undef ARG_LEN
|
||||
+ if (end_of_file &&
|
||||
+ ((n > 0 && buf[n-1] != '\0') || /* last read char not null */
|
||||
+ (n <= 0 && rbuf[tot-1] != '\0'))) /* last read char not null */
|
||||
buf[n++] = '\0'; /* so append null-terminator */
|
||||
+
|
||||
+ if (n <= 0) break; /* unneeded (end_of_file = 1) but avoid realloc */
|
||||
rbuf = xrealloc(rbuf, tot + n); /* allocate more memory */
|
||||
memcpy(rbuf + tot, buf, n); /* copy buffer into it */
|
||||
tot += n; /* increment total byte ctr */
|
||||
@@ -696,29 +702,34 @@ static char** file2strvec(const char* directory, const char* what) {
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
- if (n <= 0 && !end_of_file) {
|
||||
+ if (n < 0 || tot <= 0) { /* error, or nothing read */
|
||||
if (rbuf) free(rbuf);
|
||||
return NULL; /* read error */
|
||||
}
|
||||
+ rbuf[tot-1] = '\0'; /* belt and suspenders (the while loop did it, too) */
|
||||
endbuf = rbuf + tot; /* count space for pointers */
|
||||
align = (sizeof(char*)-1) - ((tot + sizeof(char*)-1) & (sizeof(char*)-1));
|
||||
- for (c = 0, p = rbuf; p < endbuf; p++) {
|
||||
- if (!*p || *p == '\n')
|
||||
+ c = sizeof(char*); /* one extra for NULL term */
|
||||
+ for (p = rbuf; p < endbuf; p++) {
|
||||
+ if (!*p || *p == '\n') {
|
||||
+ if (c >= INT_MAX - (tot + (int)sizeof(char*) + align)) break;
|
||||
c += sizeof(char*);
|
||||
+ }
|
||||
if (*p == '\n')
|
||||
*p = 0;
|
||||
}
|
||||
- c += sizeof(char*); /* one extra for NULL term */
|
||||
|
||||
rbuf = xrealloc(rbuf, tot + c + align); /* make room for ptrs AT END */
|
||||
endbuf = rbuf + tot; /* addr just past data buf */
|
||||
q = ret = (char**) (endbuf+align); /* ==> free(*ret) to dealloc */
|
||||
- *q++ = p = rbuf; /* point ptrs to the strings */
|
||||
- endbuf--; /* do not traverse final NUL */
|
||||
- while (++p < endbuf)
|
||||
- if (!*p) /* NUL char implies that */
|
||||
- *q++ = p+1; /* next string -> next char */
|
||||
-
|
||||
+ for (strp = p = rbuf; p < endbuf; p++) {
|
||||
+ if (!*p) { /* NUL char implies that */
|
||||
+ if (c < 2 * (int)sizeof(char*)) break;
|
||||
+ c -= sizeof(char*);
|
||||
+ *q++ = strp; /* point ptrs to the strings */
|
||||
+ strp = p+1; /* next string -> next char */
|
||||
+ }
|
||||
+ }
|
||||
*q = 0; /* null ptr list terminator */
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.14.3
|
||||
|
@ -3,23 +3,12 @@
|
||||
|
||||
Summary: System and process monitoring utilities
|
||||
Name: procps-ng
|
||||
Version: 3.3.17
|
||||
Release: 9%{?dist}
|
||||
Version: 4.0.2
|
||||
Release: 1%{?dist}
|
||||
License: GPL+ and GPLv2 and GPLv2+ and GPLv3+ and LGPLv2+
|
||||
URL: https://sourceforge.net/projects/procps-ng/
|
||||
|
||||
Source0: https://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.xz
|
||||
# README files are missing in latest tarball
|
||||
# wget https://gitlab.com/procps-ng/procps/raw/e0784ddaed30d095bb1d9a8ad6b5a23d10a212c4/README.md
|
||||
Source1: README.md
|
||||
# wget https://gitlab.com/procps-ng/procps/raw/e0784ddaed30d095bb1d9a8ad6b5a23d10a212c4/top/README.top
|
||||
Source2: README.top
|
||||
|
||||
Patch1: pwait-to-pidwait.patch
|
||||
Patch2: covscan-findings.patch
|
||||
Patch3: sysctl-hyphen-param.patch
|
||||
Patch4: free-si-fix.patch
|
||||
Patch5: sysctl-print-dotted-keys-again.patch
|
||||
|
||||
|
||||
BuildRequires: make
|
||||
@ -38,7 +27,7 @@ BuildRequires: dejagnu
|
||||
%endif
|
||||
|
||||
Provides: procps = %{version}-%{release}
|
||||
Obsoletes: procps < 3.2.9-1
|
||||
Obsoletes: procps < 4.0.1-1
|
||||
|
||||
# usrmove hack - will be removed once initscripts are fixed
|
||||
Provides: /sbin/sysctl
|
||||
@ -72,7 +61,7 @@ waits for processes of specified names.
|
||||
Summary: System and process monitoring utilities
|
||||
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||
Provides: procps-devel = %{version}-%{release}
|
||||
Obsoletes: procps-devel < 3.2.9-1
|
||||
Obsoletes: procps-devel < 3.3.17-8
|
||||
|
||||
%description devel
|
||||
System and process monitoring utilities development headers
|
||||
@ -91,11 +80,7 @@ Conflicts: man-pages-pl < 0.7-5
|
||||
Internationalization pack for procps-ng
|
||||
|
||||
%prep
|
||||
%setup -q -n procps-%{version}
|
||||
%autopatch -p1
|
||||
|
||||
cp -p %{SOURCE1} .
|
||||
cp -p %{SOURCE2} top/
|
||||
%autosetup -S git
|
||||
|
||||
%build
|
||||
# The following stuff is needed for git archives only
|
||||
@ -106,7 +91,6 @@ autoreconf --verbose --force --install
|
||||
|
||||
%configure \
|
||||
--exec-prefix=/ \
|
||||
--docdir=/unwanted \
|
||||
--disable-static \
|
||||
--disable-w-from \
|
||||
--disable-kill \
|
||||
@ -140,29 +124,30 @@ ln -s %{_bindir}/pidof %{buildroot}%{_sbindir}/pidof
|
||||
%ldconfig_scriptlets
|
||||
|
||||
%files
|
||||
%doc AUTHORS Documentation/bugs.md Documentation/FAQ NEWS README.md top/README.top Documentation/TODO
|
||||
%doc AUTHORS bugs.md FAQ NEWS README.md
|
||||
%license COPYING COPYING.LIB
|
||||
%{_libdir}/libprocps.so.*
|
||||
%{_libdir}/libproc2.so.*
|
||||
%{_bindir}/*
|
||||
%{_sbindir}/*
|
||||
%{_mandir}/man1/*
|
||||
%{_mandir}/man8/*
|
||||
%{_mandir}/man5/*
|
||||
|
||||
|
||||
%exclude %{_libdir}/libprocps.la
|
||||
%exclude /unwanted/*
|
||||
%exclude %{_pkgdocdir}/libproc.supp
|
||||
|
||||
%files devel
|
||||
%license COPYING COPYING.LIB
|
||||
%{_libdir}/libprocps.so
|
||||
%{_libdir}/pkgconfig/libprocps.pc
|
||||
%{_includedir}/proc
|
||||
%{_libdir}/libproc2.so
|
||||
%{_libdir}/pkgconfig/libproc2.pc
|
||||
%{_includedir}/libproc2
|
||||
%{_mandir}/man3/*
|
||||
|
||||
%files i18n -f %{name}.lang
|
||||
|
||||
%changelog
|
||||
* Mon Feb 13 2023 Jan Rybar <jrybar@redhat.com> - 4.0.2-1
|
||||
- rebase to 4.0.2
|
||||
|
||||
* Fri Jan 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 3.3.17-9
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
diff --git a/ps/output.c b/ps/output.c
|
||||
index e718f19..b66d543 100644
|
||||
--- a/ps/output.c
|
||||
+++ b/ps/output.c
|
||||
@@ -1250,6 +1250,26 @@ static int pr_luid(char *restrict const outbuf, const proc_t *restrict const pp)
|
||||
}
|
||||
|
||||
|
||||
+/* full path to executable */
|
||||
+static int pr_exe(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
+ char filename[48];
|
||||
+ ssize_t num_read = 0;
|
||||
+
|
||||
+ snprintf(filename, sizeof filename, "/proc/%d/exe", pp->tgid);
|
||||
+
|
||||
+ num_read = readlink(filename, outbuf, OUTBUF_SIZE-1);
|
||||
+ if (num_read > 0) {
|
||||
+ outbuf[num_read] = '\0';
|
||||
+ }
|
||||
+ else {
|
||||
+ outbuf[0] = '-';
|
||||
+ outbuf[1] = '\0';
|
||||
+ num_read = 1;
|
||||
+ }
|
||||
+
|
||||
+ return num_read;
|
||||
+}
|
||||
+
|
||||
/************************* Systemd stuff ********************************/
|
||||
static int pr_sd_unit(char *restrict const outbuf, const proc_t *restrict const pp){
|
||||
return snprintf(outbuf, COLWID, "%s", pp->sd_unit);
|
||||
@@ -1533,6 +1553,7 @@ static const format_struct format_array[] = {
|
||||
{"etimes", "ELAPSED", pr_etimes, sr_etime, 7, 0, BSD, ET|RIGHT}, /* FreeBSD */
|
||||
{"euid", "EUID", pr_euid, sr_euid, 5, 0, LNX, ET|RIGHT},
|
||||
{"euser", "EUSER", pr_euser, sr_euser, 8, USR, LNX, ET|USER},
|
||||
+{"exe", "EXE", pr_exe, sr_nop, 27, 0, LNX, PO|UNLIMITED},
|
||||
{"f", "F", pr_flag, sr_flags, 1, 0, XXX, ET|RIGHT}, /*flags*/
|
||||
{"fgid", "FGID", pr_fgid, sr_fgid, 5, 0, LNX, ET|RIGHT},
|
||||
{"fgroup", "FGROUP", pr_fgroup, sr_fgroup, 8, GRP, LNX, ET|USER},
|
||||
diff --git a/ps/ps.1 b/ps/ps.1
|
||||
index 844341c..6818667 100644
|
||||
--- a/ps/ps.1
|
||||
+++ b/ps/ps.1
|
||||
@@ -1253,6 +1253,14 @@ option can be used to force the decimal representation. (alias
|
||||
.BR uname ", " user ).
|
||||
T}
|
||||
|
||||
+exe EXE T{
|
||||
+path to the executable. Useful if path cannot be printed via
|
||||
+.BR cmd ", " comm
|
||||
+or
|
||||
+.BR args
|
||||
+format options.
|
||||
+T}
|
||||
+
|
||||
f F T{
|
||||
flags associated with the process, see the
|
||||
.B PROCESS FLAGS
|
@ -1,286 +0,0 @@
|
||||
From 52afb3a8d31871d28b1c39573a7ed5196c2d5023 Mon Sep 17 00:00:00 2001
|
||||
From: Craig Small <csmall@dropbear.xyz>
|
||||
Date: Mon, 15 Feb 2021 21:10:06 +1100
|
||||
Subject: [PATCH] pidwait: Rename from pwait
|
||||
|
||||
pwait is already in at least Debian in a different package
|
||||
|
||||
References:
|
||||
https://bugs.debian.org/982391
|
||||
---
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index e037e4c..de15e13 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -49,8 +49,8 @@ bin_PROGRAMS = \
|
||||
uptime \
|
||||
vmstat \
|
||||
w
|
||||
-if BUILD_PWAIT
|
||||
-bin_PROGRAMS += pwait
|
||||
+if BUILD_PIDWAIT
|
||||
+bin_PROGRAMS += pidwait
|
||||
endif
|
||||
else
|
||||
usrbin_exec_PROGRAMS += \
|
||||
@@ -85,8 +85,8 @@ dist_man_MANS += \
|
||||
sysctl.conf.5 \
|
||||
ps/ps.1
|
||||
|
||||
-if BUILD_PWAIT
|
||||
-dist_man_MANS += pwait.1
|
||||
+if BUILD_PIDWAIT
|
||||
+dist_man_MANS += pidwait.1
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -199,8 +199,8 @@ free_SOURCES = free.c lib/strutils.c lib/fileutils.c
|
||||
pgrep_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c
|
||||
pkill_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c
|
||||
pmap_SOURCES = pmap.c lib/fileutils.c
|
||||
-if BUILD_PWAIT
|
||||
-pwait_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c
|
||||
+if BUILD_PIDWAIT
|
||||
+pidwait_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c
|
||||
endif
|
||||
if !CYGWIN
|
||||
pwdx_SOURCES = pwdx.c lib/fileutils.c
|
||||
diff --git a/NEWS b/NEWS
|
||||
index da63c9c..5fe6761 100644
|
||||
--- a/NEWS
|
||||
+++ b/NEWS
|
||||
@@ -1,3 +1,7 @@
|
||||
+procps-ng-NEXT
|
||||
+---------------
|
||||
+ * Rename pwait to pidwait
|
||||
+
|
||||
procps-ng-3.3.17
|
||||
---------------
|
||||
* library: Incremented to 8:3:0
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 56a8669..750c0fb 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -132,20 +132,20 @@ AC_TRY_COMPILE([#include <errno.h>],
|
||||
AC_MSG_RESULT(yes),
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
-AC_CHECK_FUNC([pidfd_open], [enable_pwait=yes], [
|
||||
+AC_CHECK_FUNC([pidfd_open], [enable_pidwait=yes], [
|
||||
AC_MSG_CHECKING([for __NR_pidfd_open])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
#include <sys/syscall.h>
|
||||
#ifndef __NR_pidfd_open
|
||||
#error __NR_pidfd_open not defined
|
||||
#endif
|
||||
- ])], [enable_pwait=yes], [enable_pwait=no])
|
||||
- AC_MSG_RESULT([$enable_pwait])
|
||||
+ ])], [enable_pidwait=yes], [enable_pidwait=no])
|
||||
+ AC_MSG_RESULT([$enable_pidwait])
|
||||
])
|
||||
-if test "$enable_pwait" = yes; then
|
||||
- AC_DEFINE([ENABLE_PWAIT], [1], [Enable pwait])
|
||||
+if test "$enable_pidwait" = yes; then
|
||||
+ AC_DEFINE([ENABLE_PIDWAIT], [1], [Enable pidwait])
|
||||
fi
|
||||
-AM_CONDITIONAL([BUILD_PWAIT], [test x$enable_pwait = xyes])
|
||||
+AM_CONDITIONAL([BUILD_PIDWAIT], [test x$enable_pidwait = xyes])
|
||||
|
||||
dnl watch8bit must be before the AC_ARG_WITH set as it sets up ncurses
|
||||
AC_SUBST([WITH_WATCH8BIT])
|
||||
diff --git a/pgrep.1 b/pgrep.1
|
||||
index 4f8907b..af6dcd5 100644
|
||||
--- a/pgrep.1
|
||||
+++ b/pgrep.1
|
||||
@@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.TH PGREP "1" "2020-06-04" "procps-ng" "User Commands"
|
||||
.SH NAME
|
||||
-pgrep, pkill, pwait \- look up, signal, or wait for processes based on name and other attributes
|
||||
+pgrep, pkill, pidwait \- look up, signal, or wait for processes based on name and other attributes
|
||||
.SH SYNOPSIS
|
||||
.B pgrep
|
||||
[options] pattern
|
||||
@@ -17,7 +17,7 @@ pgrep, pkill, pwait \- look up, signal, or wait for processes based on name and
|
||||
.B pkill
|
||||
[options] pattern
|
||||
.br
|
||||
-.B pwait
|
||||
+.B pidwait
|
||||
[options] pattern
|
||||
.SH DESCRIPTION
|
||||
.B pgrep
|
||||
@@ -45,7 +45,7 @@ will send the specified signal (by default
|
||||
.BR SIGTERM )
|
||||
to each process instead of listing them on stdout.
|
||||
.PP
|
||||
-.B pwait
|
||||
+.B pidwait
|
||||
will wait for each process instead of listing them on stdout.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
@@ -60,7 +60,7 @@ only.)
|
||||
\fB\-c\fR, \fB\-\-count\fR
|
||||
Suppress normal output; instead print a count of matching processes. When
|
||||
count does not match anything, e.g. returns zero, the command will return
|
||||
-non-zero value. Note that for pkill and pwait, the count is the number of
|
||||
+non-zero value. Note that for pkill and pidwait, the count is the number of
|
||||
matching processes, not the processes that were successfully signaled or waited
|
||||
for.
|
||||
.TP
|
||||
@@ -88,7 +88,7 @@ translated into
|
||||
.BR pgrep 's,
|
||||
.BR pkill 's,
|
||||
or
|
||||
-.BR pwait 's
|
||||
+.BR pidwait 's
|
||||
own process group.
|
||||
.TP
|
||||
\fB\-G\fR, \fB\-\-group\fR \fIgid\fP,...
|
||||
@@ -126,7 +126,7 @@ is translated into
|
||||
.BR pgrep 's,
|
||||
.BR pkill 's,
|
||||
or
|
||||
-.BR pwait 's
|
||||
+.BR pidwait 's
|
||||
own session ID.
|
||||
.TP
|
||||
\fB\-t\fR, \fB\-\-terminal\fR \fIterm\fP,...
|
||||
@@ -145,7 +145,7 @@ symbolical value may be used.
|
||||
Negates the matching. This option is usually used in
|
||||
.BR pgrep 's
|
||||
or
|
||||
-.BR pwait 's
|
||||
+.BR pidwait 's
|
||||
context. In
|
||||
.BR pkill 's
|
||||
context the short option is disabled to avoid accidental usage of the option.
|
||||
@@ -154,7 +154,7 @@ context the short option is disabled to avoid accidental usage of the option.
|
||||
Shows all thread ids instead of pids in
|
||||
.BR pgrep 's
|
||||
or
|
||||
-.BR pwait 's
|
||||
+.BR pidwait 's
|
||||
context. In
|
||||
.BR pkill 's
|
||||
context this option is disabled.
|
||||
@@ -167,7 +167,7 @@ match the
|
||||
.TP
|
||||
\fB\-F\fR, \fB\-\-pidfile\fR \fIfile\fR
|
||||
Read \fIPID\fRs from \fIfile\fR. This option is more useful for
|
||||
-.BR pkill or pwait
|
||||
+.BR pkill or pidwait
|
||||
than
|
||||
.BR pgrep .
|
||||
.TP
|
||||
@@ -237,7 +237,7 @@ $ renice +4 $(pgrep chrome)
|
||||
.PD 0
|
||||
.TP
|
||||
0
|
||||
-One or more processes matched the criteria. For pkill and pwait, one or more
|
||||
+One or more processes matched the criteria. For pkill and pidwait, one or more
|
||||
processes must also have been successfully signalled or waited for.
|
||||
.TP
|
||||
1
|
||||
@@ -258,7 +258,7 @@ The running
|
||||
.BR pgrep ,
|
||||
.BR pkill ,
|
||||
or
|
||||
-.B pwait
|
||||
+.B pidwait
|
||||
process will never report itself as a
|
||||
match.
|
||||
.SH BUGS
|
||||
diff --git a/pgrep.c b/pgrep.c
|
||||
index 4fe5e8a..1905cd1 100644
|
||||
--- a/pgrep.c
|
||||
+++ b/pgrep.c
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
-#if defined(ENABLE_PWAIT) && !defined(HAVE_PIDFD_OPEN)
|
||||
+#if defined(ENABLE_PIDWAIT) && !defined(HAVE_PIDFD_OPEN)
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
@@ -68,8 +68,8 @@
|
||||
static enum {
|
||||
PGREP = 0,
|
||||
PKILL,
|
||||
-#ifdef ENABLE_PWAIT
|
||||
- PWAIT,
|
||||
+#ifdef ENABLE_PIDWAIT
|
||||
+ PIDWAIT,
|
||||
#endif
|
||||
} prog_mode;
|
||||
|
||||
@@ -136,8 +136,8 @@ static int __attribute__ ((__noreturn__)) usage(int opt)
|
||||
fputs(_(" -q, --queue <value> integer value to be sent with the signal\n"), fp);
|
||||
fputs(_(" -e, --echo display what is killed\n"), fp);
|
||||
break;
|
||||
-#ifdef ENABLE_PWAIT
|
||||
- case PWAIT:
|
||||
+#ifdef ENABLE_PIDWAIT
|
||||
+ case PIDWAIT:
|
||||
fputs(_(" -e, --echo display PIDs before waiting\n"), fp);
|
||||
break;
|
||||
#endif
|
||||
@@ -687,7 +687,7 @@ static struct el * select_procs (int *num)
|
||||
xerrx(EXIT_FAILURE, _("internal error"));
|
||||
}
|
||||
|
||||
- // pkill and pwait don't support -w, but this is checked in getopt
|
||||
+ // pkill and pidwait don't support -w, but this is checked in getopt
|
||||
if (opt_threads) {
|
||||
while (readtask(ptp, &task, &subtask)){
|
||||
// don't add redundant tasks
|
||||
@@ -742,7 +742,7 @@ static int signal_option(int *argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
-#if defined(ENABLE_PWAIT) && !defined(HAVE_PIDFD_OPEN)
|
||||
+#if defined(ENABLE_PIDWAIT) && !defined(HAVE_PIDFD_OPEN)
|
||||
static int pidfd_open (pid_t pid, unsigned int flags)
|
||||
{
|
||||
return syscall(__NR_pidfd_open, pid, flags);
|
||||
@@ -793,9 +793,9 @@ static void parse_opts (int argc, char **argv)
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
-#ifdef ENABLE_PWAIT
|
||||
- if (strcmp (program_invocation_short_name, "pwait") == 0) {
|
||||
- prog_mode = PWAIT;
|
||||
+#ifdef ENABLE_PIDWAIT
|
||||
+ if (strcmp (program_invocation_short_name, "pidwait") == 0) {
|
||||
+ prog_mode = PIDWAIT;
|
||||
strcat (opts, "e");
|
||||
} else
|
||||
#endif
|
||||
@@ -1008,7 +1008,7 @@ int main (int argc, char **argv)
|
||||
int num;
|
||||
int i;
|
||||
int kill_count = 0;
|
||||
-#ifdef ENABLE_PWAIT
|
||||
+#ifdef ENABLE_PIDWAIT
|
||||
int poll_count = 0;
|
||||
int wait_count = 0;
|
||||
int epollfd = epoll_create(1);
|
||||
@@ -1055,8 +1055,8 @@ int main (int argc, char **argv)
|
||||
fprintf(stdout, "%d\n", num);
|
||||
return !kill_count;
|
||||
|
||||
-#ifdef ENABLE_PWAIT
|
||||
- case PWAIT:
|
||||
+#ifdef ENABLE_PIDWAIT
|
||||
+ case PIDWAIT:
|
||||
if (opt_count)
|
||||
fprintf(stdout, "%d\n", num);
|
||||
|
||||
diff --git a/pwait.1 b/pidwait.1
|
||||
similarity index 100%
|
||||
rename from pwait.1
|
||||
rename to pidwait.1
|
||||
--
|
||||
GitLab
|
||||
|
2
sources
2
sources
@ -1 +1 @@
|
||||
SHA512 (procps-ng-3.3.17.tar.xz) = 59e9a5013430fd9da508c4655d58375dc32e025bb502bb28fb9a92a48e4f2838b3355e92b4648f7384b2050064d17079bf4595d889822ebb5030006bc154a1a7
|
||||
SHA512 (procps-ng-4.0.2.tar.xz) = 5327e62084bf801786785aad98cc2f0463f48336864d1dd92d138097ffaac7ffbc8d5127b325a0e9d06b29d101f19bbfaecf612f659035b00e6627cb5e267544
|
||||
|
@ -1,833 +0,0 @@
|
||||
diff -up ./NEWS.ori ./NEWS
|
||||
diff -up ./sysctl.c.ori ./sysctl.c
|
||||
--- ./sysctl.c.ori 2021-02-09 11:11:25.000000000 +0100
|
||||
+++ ./sysctl.c 2022-03-31 18:27:36.536486629 +0200
|
||||
@@ -17,6 +17,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
+ * Part of this code comes from systemd, especially sysctl.c
|
||||
* Changelog:
|
||||
* v1.01:
|
||||
* - added -p <preload> to preload values from a file
|
||||
@@ -40,6 +41,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
+#include <ctype.h>
|
||||
|
||||
#include "c.h"
|
||||
#include "fileutils.h"
|
||||
@@ -66,12 +68,34 @@ static bool PrintName;
|
||||
static bool PrintNewline;
|
||||
static bool IgnoreError;
|
||||
static bool Quiet;
|
||||
+static bool DryRun;
|
||||
static char *pattern;
|
||||
|
||||
#define LINELEN 4096
|
||||
static char *iobuf;
|
||||
static size_t iolen = LINELEN;
|
||||
|
||||
+typedef struct SysctlSetting {
|
||||
+ char *key;
|
||||
+ char *path;
|
||||
+ char *value;
|
||||
+ bool ignore_failure;
|
||||
+ bool glob_exclude;
|
||||
+ struct SysctlSetting *next;
|
||||
+} SysctlSetting;
|
||||
+
|
||||
+typedef struct SettingList {
|
||||
+ struct SysctlSetting *head;
|
||||
+ struct SysctlSetting *tail;
|
||||
+} SettingList;
|
||||
+
|
||||
+#define GLOB_CHARS "*?["
|
||||
+static inline bool string_is_glob(const char *p)
|
||||
+{
|
||||
+ return !!strpbrk(p, GLOB_CHARS);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Function prototypes. */
|
||||
static int pattern_match(const char *string, const char *pat);
|
||||
static int DisplayAll(const char *restrict const path);
|
||||
@@ -100,6 +124,81 @@ static void slashdot(char *restrict p, c
|
||||
}
|
||||
}
|
||||
|
||||
+static void setting_free(SysctlSetting *s) {
|
||||
+ if (!s)
|
||||
+ return;
|
||||
+
|
||||
+ free(s->key);
|
||||
+ free(s->path);
|
||||
+ free(s->value);
|
||||
+ free(s);
|
||||
+}
|
||||
+
|
||||
+static SysctlSetting *setting_new(
|
||||
+ const char *key,
|
||||
+ const char *value,
|
||||
+ bool ignore_failure,
|
||||
+ bool glob_exclude) {
|
||||
+
|
||||
+ SysctlSetting *s = NULL;
|
||||
+ char *path = NULL;
|
||||
+ int proc_len;
|
||||
+
|
||||
+ proc_len = strlen(PROC_PATH);
|
||||
+ /* used to open the file */
|
||||
+ path = xmalloc(strlen(key) + proc_len + 2);
|
||||
+ strcpy(path, PROC_PATH);
|
||||
+ if (key[0] == '-')
|
||||
+ strcat(path + proc_len, key+1);
|
||||
+ else
|
||||
+ strcat(path + proc_len, key);
|
||||
+ /* change . to / */
|
||||
+ slashdot(path + proc_len, '.', '/');
|
||||
+
|
||||
+ s = xmalloc(sizeof(SysctlSetting));
|
||||
+
|
||||
+ *s = (SysctlSetting) {
|
||||
+ .key = strdup(key),
|
||||
+ .path = path,
|
||||
+ .value = value? strdup(value): NULL,
|
||||
+ .ignore_failure = ignore_failure,
|
||||
+ .glob_exclude = glob_exclude,
|
||||
+ .next = NULL,
|
||||
+ };
|
||||
+
|
||||
+ return s;
|
||||
+}
|
||||
+
|
||||
+static void settinglist_add(SettingList *l, SysctlSetting *s) {
|
||||
+ SysctlSetting *old_tail;
|
||||
+
|
||||
+ if (!l)
|
||||
+ return;
|
||||
+
|
||||
+ if (l->head == NULL)
|
||||
+ l->head = s;
|
||||
+
|
||||
+ if (l->tail != NULL) {
|
||||
+ old_tail = l->tail;
|
||||
+ old_tail->next = s;
|
||||
+ }
|
||||
+ l->tail = s;
|
||||
+}
|
||||
+
|
||||
+static SysctlSetting *settinglist_findpath(const SettingList *l, const char *path) {
|
||||
+ SysctlSetting *node;
|
||||
+
|
||||
+ for (node=l->head; node != NULL; node = node->next) {
|
||||
+ if (strcmp(node->path, path) == 0)
|
||||
+ return node;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* Function prototypes. */
|
||||
+static int pattern_match(const char *string, const char *pat);
|
||||
+static int DisplayAll(const char *restrict const path);
|
||||
+
|
||||
/*
|
||||
* Display the usage format
|
||||
*/
|
||||
@@ -115,6 +214,7 @@ static void __attribute__ ((__noreturn__
|
||||
fputs(_(" -A alias of -a\n"), out);
|
||||
fputs(_(" -X alias of -a\n"), out);
|
||||
fputs(_(" --deprecated include deprecated parameters to listing\n"), out);
|
||||
+ fputs(_(" --dry-run Print the key and values but do not write\n"), out);
|
||||
fputs(_(" -b, --binary print value without new line\n"), out);
|
||||
fputs(_(" -e, --ignore ignore unknown variables errors\n"), out);
|
||||
fputs(_(" -N, --names print variable names without values\n"), out);
|
||||
@@ -138,6 +238,39 @@ static void __attribute__ ((__noreturn__
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Strip left/leading side of a string
|
||||
+ */
|
||||
+static char *lstrip(char *line)
|
||||
+{
|
||||
+ char *start;
|
||||
+
|
||||
+ if (!line || !*line)
|
||||
+ return line;
|
||||
+
|
||||
+ start = line;
|
||||
+ while(isspace(*start)) start++;
|
||||
+
|
||||
+ return start;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Strip right/trailing side of a string
|
||||
+ * by placing a \0
|
||||
+ */
|
||||
+static void rstrip(char *line)
|
||||
+{
|
||||
+ char *end;
|
||||
+
|
||||
+ if (!line || !*line)
|
||||
+ return;
|
||||
+
|
||||
+ end = line + strlen(line) - 1;
|
||||
+ while(end > line && isspace(*end)) end--;
|
||||
+
|
||||
+ end[1] = '\0';
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* Strip the leading and trailing spaces from a string
|
||||
*/
|
||||
static char *StripLeadingAndTrailingSpaces(char *oneline)
|
||||
@@ -166,7 +299,7 @@ static char *StripLeadingAndTrailingSpac
|
||||
*/
|
||||
static int ReadSetting(const char *restrict const name)
|
||||
{
|
||||
- int rc = 0;
|
||||
+ int rc = EXIT_SUCCESS;
|
||||
char *restrict tmpname;
|
||||
char *restrict outname;
|
||||
ssize_t rlen;
|
||||
@@ -198,7 +331,7 @@ static int ReadSetting(const char *restr
|
||||
if (stat(tmpname, &ts) < 0) {
|
||||
if (!IgnoreError) {
|
||||
xwarn(_("cannot stat %s"), tmpname);
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
@@ -215,7 +348,7 @@ static int ReadSetting(const char *restr
|
||||
}
|
||||
|
||||
if (pattern && !pattern_match(outname, pattern)) {
|
||||
- rc = 0;
|
||||
+ rc = EXIT_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -231,19 +364,19 @@ static int ReadSetting(const char *restr
|
||||
case ENOENT:
|
||||
if (!IgnoreError) {
|
||||
xwarnx(_("\"%s\" is an unknown key"), outname);
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case EACCES:
|
||||
xwarnx(_("permission denied on key '%s'"), outname);
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
break;
|
||||
case EIO: /* Ignore stable_secret below /proc/sys/net/ipv6/conf */
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
break;
|
||||
default:
|
||||
xwarn(_("reading key \"%s\""), outname);
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -279,7 +412,7 @@ static int ReadSetting(const char *restr
|
||||
case EACCES:
|
||||
xwarnx(_("permission denied on key '%s'"),
|
||||
outname);
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
break;
|
||||
case EISDIR: {
|
||||
size_t len;
|
||||
@@ -291,11 +424,11 @@ static int ReadSetting(const char *restr
|
||||
goto out;
|
||||
}
|
||||
case EIO: /* Ignore stable_secret below /proc/sys/net/ipv6/conf */
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
break;
|
||||
default:
|
||||
xwarnx(_("reading key \"%s\""), outname);
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
@@ -323,7 +456,7 @@ static int is_deprecated(char *filename)
|
||||
*/
|
||||
static int DisplayAll(const char *restrict const path)
|
||||
{
|
||||
- int rc = 0;
|
||||
+ int rc = EXIT_SUCCESS;
|
||||
int rc2;
|
||||
DIR *restrict dp;
|
||||
struct dirent *restrict de;
|
||||
@@ -333,7 +466,7 @@ static int DisplayAll(const char *restri
|
||||
|
||||
if (!dp) {
|
||||
xwarnx(_("unable to open directory \"%s\""), path);
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
} else {
|
||||
readdir(dp); /* skip . */
|
||||
readdir(dp); /* skip .. */
|
||||
@@ -369,130 +502,183 @@ static int DisplayAll(const char *restri
|
||||
/*
|
||||
* Write a sysctl setting
|
||||
*/
|
||||
-static int WriteSetting(const char *setting)
|
||||
-{
|
||||
- int rc = 0;
|
||||
- const char *name = setting;
|
||||
- const char *value;
|
||||
- const char *equals;
|
||||
- char *tmpname;
|
||||
- char *outname;
|
||||
- char *last_dot;
|
||||
- bool ignore_failure;
|
||||
+static int WriteSetting(
|
||||
+ const char *key,
|
||||
+ const char *path,
|
||||
+ const char *value,
|
||||
+ const bool ignore_failure) {
|
||||
|
||||
- FILE *fp;
|
||||
+ int rc = EXIT_SUCCESS;
|
||||
+ FILE *fp;
|
||||
struct stat ts;
|
||||
|
||||
- if (!name)
|
||||
- /* probably don't want to display this err */
|
||||
- return 0;
|
||||
-
|
||||
- equals = strchr(setting, '=');
|
||||
-
|
||||
- if (!equals) {
|
||||
- xwarnx(_("\"%s\" must be of the form name=value"),
|
||||
- setting);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* point to the value in name=value */
|
||||
- value = equals + 1;
|
||||
-
|
||||
- if (!*name || name == equals) {
|
||||
- xwarnx(_("malformed setting \"%s\""), setting);
|
||||
- return -2;
|
||||
- }
|
||||
-
|
||||
- ignore_failure = name[0] == '-';
|
||||
- if (ignore_failure)
|
||||
- name++;
|
||||
+ if (!key || !path)
|
||||
+ return rc;
|
||||
|
||||
- /* used to open the file */
|
||||
- tmpname = xmalloc(equals - name + 1 + strlen(PROC_PATH));
|
||||
- strcpy(tmpname, PROC_PATH);
|
||||
- strncat(tmpname, name, (int) (equals - name));
|
||||
- tmpname[equals - name + strlen(PROC_PATH)] = 0;
|
||||
- /* change . to / */
|
||||
- slashdot(tmpname + strlen(PROC_PATH), '.', '/');
|
||||
-
|
||||
- /* used to display the output */
|
||||
- outname = xmalloc(equals - name + 1);
|
||||
- strncpy(outname, name, (int) (equals - name));
|
||||
- outname[equals - name] = 0;
|
||||
- /* change / to . */
|
||||
- slashdot(outname, '/', '.');
|
||||
- last_dot = strrchr(outname, '.');
|
||||
- if (last_dot != NULL && is_deprecated(last_dot + 1)) {
|
||||
- xwarnx(_("%s is deprecated, value not set"), outname);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (stat(tmpname, &ts) < 0) {
|
||||
+ if (stat(path, &ts) < 0) {
|
||||
if (!IgnoreError) {
|
||||
- xwarn(_("cannot stat %s"), tmpname);
|
||||
- rc = -1;
|
||||
+ xwarn(_("cannot stat %s"), path);
|
||||
+ rc = EXIT_FAILURE;
|
||||
}
|
||||
- goto out;
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
if ((ts.st_mode & S_IWUSR) == 0) {
|
||||
- xwarn(_("setting key \"%s\""), outname);
|
||||
- goto out;
|
||||
+ xwarn(_("setting key \"%s\""), key);
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
if (S_ISDIR(ts.st_mode)) {
|
||||
- xwarn(_("setting key \"%s\""), outname);
|
||||
- goto out;
|
||||
+ xwarn(_("setting key \"%s\""), key);
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
- fp = fprocopen(tmpname, "w");
|
||||
-
|
||||
- if (!fp) {
|
||||
- switch (errno) {
|
||||
- case ENOENT:
|
||||
- if (!IgnoreError) {
|
||||
- xwarnx(_("\"%s\" is an unknown key%s"), outname, (ignore_failure?_(", ignoring"):""));
|
||||
+ if (!DryRun) {
|
||||
+ if ((fp = fprocopen(path, "w")) == NULL) {
|
||||
+ switch (errno) {
|
||||
+ case ENOENT:
|
||||
+ if (!IgnoreError) {
|
||||
+ xwarnx(_("\"%s\" is an unknown key%s"),
|
||||
+ key, (ignore_failure?_(", ignoring"):""));
|
||||
if (!ignore_failure)
|
||||
- rc = -1;
|
||||
+ rc = EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
- case EPERM:
|
||||
- case EROFS:
|
||||
- case EACCES:
|
||||
- xwarnx(_("permission denied on key \"%s\"%s"), outname, (ignore_failure?_(", ignoring"):""));
|
||||
- break;
|
||||
- default:
|
||||
- xwarn(_("setting key \"%s\"%s"), outname, (ignore_failure?_(", ignoring"):""));
|
||||
- break;
|
||||
- }
|
||||
- if (!ignore_failure && errno != ENOENT)
|
||||
- rc = -1;
|
||||
- } else {
|
||||
- rc = fprintf(fp, "%s\n", value);
|
||||
- if (0 < rc)
|
||||
- rc = 0;
|
||||
- if (close_stream(fp) != 0)
|
||||
- xwarn(_("setting key \"%s\""), outname);
|
||||
- else if (rc == 0 && !Quiet) {
|
||||
- if (NameOnly) {
|
||||
- fprintf(stdout, "%s\n", outname);
|
||||
- } else {
|
||||
- if (PrintName) {
|
||||
- fprintf(stdout, "%s = %s\n",
|
||||
- outname, value);
|
||||
- } else {
|
||||
- if (PrintNewline)
|
||||
- fprintf(stdout, "%s\n", value);
|
||||
- else
|
||||
- fprintf(stdout, "%s", value);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- out:
|
||||
- free(tmpname);
|
||||
- free(outname);
|
||||
- return rc;
|
||||
+ case EPERM:
|
||||
+ case EROFS:
|
||||
+ case EACCES:
|
||||
+ xwarnx(_("permission denied on key \"%s\"%s"),
|
||||
+ key, (ignore_failure?_(", ignoring"):""));
|
||||
+ break;
|
||||
+ default:
|
||||
+ xwarn(_("setting key \"%s\"%s"),
|
||||
+ key, (ignore_failure?_(", ignoring"):""));
|
||||
+ break;
|
||||
+ }
|
||||
+ if (!ignore_failure && errno != ENOENT)
|
||||
+ rc = EXIT_FAILURE;
|
||||
+ } else {
|
||||
+ if (0 < fprintf(fp, "%s\n", value))
|
||||
+ rc = EXIT_SUCCESS;
|
||||
+ if (close_stream(fp) != 0) {
|
||||
+ xwarn(_("setting key \"%s\""), path);
|
||||
+ return rc;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if ((rc == EXIT_SUCCESS && !Quiet) || DryRun) {
|
||||
+ if (NameOnly) {
|
||||
+ printf("%s\n", value);
|
||||
+ } else {
|
||||
+ if (PrintName) {
|
||||
+ printf("%s = %s\n", path, value);
|
||||
+ } else {
|
||||
+ if (PrintNewline)
|
||||
+ printf("%s\n", value);
|
||||
+ else
|
||||
+ printf("%s", value);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * parse each configuration line, there are multiple ways of specifying
|
||||
+ * a key/value here:
|
||||
+ *
|
||||
+ * key = value simple setting
|
||||
+ * -key = value ignore errors
|
||||
+ * key.pattern.*.with.glob = value set keys that match glob
|
||||
+ * -key.pattern.exclude.with.glob dont set this value
|
||||
+ * key.pattern.override.with.glob = value set this glob match to value
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+static SysctlSetting *parse_setting_line(
|
||||
+ const char *path,
|
||||
+ const int linenum,
|
||||
+ char *line)
|
||||
+{
|
||||
+ SysctlSetting *s;
|
||||
+ char *key;
|
||||
+ char *value;
|
||||
+ bool glob_exclude = FALSE;
|
||||
+ bool ignore_failure = FALSE;
|
||||
+
|
||||
+ key = lstrip(line);
|
||||
+ if (strlen(key) < 2)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* skip over comments */
|
||||
+ if (key[0] == '#' || key[0] == ';')
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (pattern && !pattern_match(key, pattern))
|
||||
+ return NULL;
|
||||
+
|
||||
+ value = strchr(key, '=');
|
||||
+ if (value == NULL) {
|
||||
+ if (key[0] == '-') {
|
||||
+ glob_exclude = TRUE;
|
||||
+ key++;
|
||||
+ value = NULL;
|
||||
+ rstrip(key);
|
||||
+ } else {
|
||||
+ xwarnx(_("%s(%d): invalid syntax, continuing..."),
|
||||
+ path, linenum);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ value[0]='\0';
|
||||
+ if (key[0] == '-') {
|
||||
+ ignore_failure = TRUE;
|
||||
+ key++;
|
||||
+ }
|
||||
+ value++; // skip over =
|
||||
+ value=lstrip(value);
|
||||
+ rstrip(value);
|
||||
+ rstrip(key);
|
||||
+ }
|
||||
+ return setting_new(key, value, ignore_failure, glob_exclude);
|
||||
+}
|
||||
+
|
||||
+/* Go through the setting list, expand and sort out
|
||||
+ * setting globs and actually write the settings out
|
||||
+ */
|
||||
+static int write_setting_list(const SettingList *sl)
|
||||
+{
|
||||
+ SysctlSetting *node;
|
||||
+ int rc = EXIT_SUCCESS;
|
||||
+
|
||||
+ for (node=sl->head; node != NULL; node=node->next) {
|
||||
+ if (node->glob_exclude)
|
||||
+ continue;
|
||||
+
|
||||
+ if (string_is_glob(node->path)) {
|
||||
+ char *gl_path;
|
||||
+ glob_t globbuf;
|
||||
+ int i;
|
||||
+
|
||||
+ if (glob(node->path, 0, NULL, &globbuf) != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ for(i=0; i < globbuf.gl_pathc; i++) {
|
||||
+ if (settinglist_findpath(sl, globbuf.gl_pathv[i]))
|
||||
+ continue; // override or exclude
|
||||
+
|
||||
+ rc |= WriteSetting(node->key, globbuf.gl_pathv[i], node->value,
|
||||
+ node->ignore_failure);
|
||||
+ }
|
||||
+ } else {
|
||||
+ rc |= WriteSetting(node->key, node->path, node->value,
|
||||
+ node->ignore_failure);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
static int pattern_match(const char *string, const char *pat)
|
||||
@@ -513,12 +699,12 @@ static int pattern_match(const char *str
|
||||
* Preload the sysctl's from the conf file. We parse the file and then
|
||||
* reform it (strip out whitespace).
|
||||
*/
|
||||
-static int Preload(const char *restrict const filename)
|
||||
+static int Preload(SettingList *setlist, const char *restrict const filename)
|
||||
{
|
||||
FILE *fp;
|
||||
char *t;
|
||||
int n = 0;
|
||||
- int rc = 0;
|
||||
+ int rc = EXIT_SUCCESS;
|
||||
ssize_t rlen;
|
||||
char *name, *value;
|
||||
glob_t globbuf;
|
||||
@@ -547,62 +733,26 @@ static int Preload(const char *restrict
|
||||
? stdin : fopen(globbuf.gl_pathv[j], "r");
|
||||
if (!fp) {
|
||||
xwarn(_("cannot open \"%s\""), globbuf.gl_pathv[j]);
|
||||
- rc = -1;
|
||||
- goto out;
|
||||
+ return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while ((rlen = getline(&iobuf, &iolen, fp)) > 0) {
|
||||
size_t offset;
|
||||
+ SysctlSetting *setting;
|
||||
|
||||
n++;
|
||||
|
||||
if (rlen < 2)
|
||||
continue;
|
||||
|
||||
- t = StripLeadingAndTrailingSpaces(iobuf);
|
||||
- if (strlen(t) < 2)
|
||||
- continue;
|
||||
-
|
||||
- if (*t == '#' || *t == ';')
|
||||
- continue;
|
||||
-
|
||||
- name = strtok(t, "=");
|
||||
- if (!name || !*name) {
|
||||
- xwarnx(_("%s(%d): invalid syntax, continuing..."),
|
||||
- globbuf.gl_pathv[j], n);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- StripLeadingAndTrailingSpaces(name);
|
||||
-
|
||||
- if (pattern && !pattern_match(name, pattern))
|
||||
- continue;
|
||||
-
|
||||
- offset = strlen(name);
|
||||
- memmove(&iobuf[0], name, offset);
|
||||
- iobuf[offset++] = '=';
|
||||
-
|
||||
- value = strtok(NULL, "\n\r");
|
||||
- if (!value || !*value) {
|
||||
- xwarnx(_("%s(%d): invalid syntax, continuing..."),
|
||||
- globbuf.gl_pathv[j], n);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- while ((*value == ' ' || *value == '\t') && *value != 0)
|
||||
- value++;
|
||||
-
|
||||
- /* should NameOnly affect this? */
|
||||
- memmove(&iobuf[offset], value, strlen(value));
|
||||
- offset += strlen(value);
|
||||
- iobuf[offset] = '\0';
|
||||
-
|
||||
- rc |= WriteSetting(iobuf);
|
||||
+ if ( (setting = parse_setting_line(globbuf.gl_pathv[j], n, iobuf))
|
||||
+ == NULL)
|
||||
+ continue;
|
||||
+ settinglist_add(setlist, setting);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
-out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -618,7 +768,7 @@ static int sortpairs(const void *A, cons
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
-static int PreloadSystem(void)
|
||||
+static int PreloadSystem(SettingList *setlist)
|
||||
{
|
||||
unsigned di, i;
|
||||
const char *dirs[] = {
|
||||
@@ -630,7 +780,7 @@ static int PreloadSystem(void)
|
||||
};
|
||||
struct pair **cfgs = NULL;
|
||||
unsigned ncfgs = 0;
|
||||
- int rc = 0;
|
||||
+ int rc = EXIT_SUCCESS;
|
||||
struct stat ts;
|
||||
enum { nprealloc = 16 };
|
||||
|
||||
@@ -688,14 +838,14 @@ static int PreloadSystem(void)
|
||||
for (i = 0; i < ncfgs; ++i) {
|
||||
if (!Quiet)
|
||||
printf(_("* Applying %s ...\n"), cfgs[i]->value);
|
||||
- rc |= Preload(cfgs[i]->value);
|
||||
+ rc |= Preload(setlist, cfgs[i]->value);
|
||||
}
|
||||
|
||||
|
||||
if (stat(DEFAULT_PRELOAD, &ts) == 0 && S_ISREG(ts.st_mode)) {
|
||||
if (!Quiet)
|
||||
printf(_("* Applying %s ...\n"), DEFAULT_PRELOAD);
|
||||
- rc |= Preload(DEFAULT_PRELOAD);
|
||||
+ rc |= Preload(setlist, DEFAULT_PRELOAD);
|
||||
}
|
||||
|
||||
/* cleaning */
|
||||
@@ -717,15 +867,19 @@ int main(int argc, char *argv[])
|
||||
bool preloadfileOpt = false;
|
||||
int ReturnCode = 0;
|
||||
int c;
|
||||
+ int rc;
|
||||
const char *preloadfile = NULL;
|
||||
+ SettingList *setlist;
|
||||
|
||||
enum {
|
||||
DEPRECATED_OPTION = CHAR_MAX + 1,
|
||||
- SYSTEM_OPTION
|
||||
+ SYSTEM_OPTION,
|
||||
+ DRYRUN_OPTION
|
||||
};
|
||||
static const struct option longopts[] = {
|
||||
{"all", no_argument, NULL, 'a'},
|
||||
{"deprecated", no_argument, NULL, DEPRECATED_OPTION},
|
||||
+ {"dry-run", no_argument, NULL, DRYRUN_OPTION},
|
||||
{"binary", no_argument, NULL, 'b'},
|
||||
{"ignore", no_argument, NULL, 'e'},
|
||||
{"names", no_argument, NULL, 'N'},
|
||||
@@ -753,6 +907,10 @@ int main(int argc, char *argv[])
|
||||
IgnoreError = false;
|
||||
Quiet = false;
|
||||
IgnoreDeprecated = true;
|
||||
+ DryRun = false;
|
||||
+ setlist = xmalloc(sizeof(SettingList));
|
||||
+ setlist->head = NULL;
|
||||
+ setlist->tail = NULL;
|
||||
|
||||
if (argc < 2)
|
||||
Usage(stderr);
|
||||
@@ -805,7 +963,12 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case SYSTEM_OPTION:
|
||||
IgnoreError = true;
|
||||
- return PreloadSystem();
|
||||
+ rc |= PreloadSystem(setlist);
|
||||
+ rc |= write_setting_list(setlist);
|
||||
+ return rc;
|
||||
+ case DRYRUN_OPTION:
|
||||
+ DryRun = true;
|
||||
+ break;
|
||||
case 'r':
|
||||
pattern = xstrdup(optarg);
|
||||
break;
|
||||
@@ -833,15 +996,16 @@ int main(int argc, char *argv[])
|
||||
int ret = EXIT_SUCCESS, i;
|
||||
if (!preloadfile) {
|
||||
if (!argc) {
|
||||
- ret |= Preload(DEFAULT_PRELOAD);
|
||||
+ ret |= Preload(setlist, DEFAULT_PRELOAD);
|
||||
}
|
||||
} else {
|
||||
/* This happens when -pfile option is
|
||||
* used without space. */
|
||||
- ret |= Preload(preloadfile);
|
||||
+ ret |= Preload(setlist, preloadfile);
|
||||
}
|
||||
for (i = 0; i < argc; i++)
|
||||
- ret |= Preload(argv[i]);
|
||||
+ ret |= Preload(setlist, argv[i]);
|
||||
+ ret |= write_setting_list(setlist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -855,9 +1019,14 @@ int main(int argc, char *argv[])
|
||||
program_invocation_short_name);
|
||||
|
||||
for ( ; *argv; argv++) {
|
||||
- if (WriteMode || strchr(*argv, '='))
|
||||
- ReturnCode += WriteSetting(*argv);
|
||||
- else
|
||||
+ if (WriteMode || strchr(*argv, '=')) {
|
||||
+ SysctlSetting *s;
|
||||
+ if ( (s = parse_setting_line("command line", 0, *argv)) != NULL)
|
||||
+ ReturnCode |= WriteSetting(s->key, s->path, s->value,
|
||||
+ s->ignore_failure);
|
||||
+ else
|
||||
+ ReturnCode |= EXIT_FAILURE;
|
||||
+ } else
|
||||
ReturnCode += ReadSetting(*argv);
|
||||
}
|
||||
return ReturnCode;
|
||||
diff -up ./testsuite/config/unix.exp.ori ./testsuite/config/unix.exp
|
||||
--- ./testsuite/config/unix.exp.ori 2021-02-09 11:11:25.000000000 +0100
|
||||
+++ ./testsuite/config/unix.exp 2022-03-31 18:27:36.536486629 +0200
|
||||
@@ -136,6 +136,15 @@ proc expect_table_dsc { test match_heade
|
||||
#}
|
||||
}
|
||||
|
||||
+proc expect_spawn_retval { test retval } {
|
||||
+ foreach {pid spawnid os_error_flag value} [wait] break
|
||||
+
|
||||
+ if {$value == $retval} {
|
||||
+ return
|
||||
+ }
|
||||
+ fail "$test (exit value)"
|
||||
+}
|
||||
+
|
||||
proc make_pipeproc { } {
|
||||
global pipeproc_pid pipeproc_spawnid topdir
|
||||
|
||||
diff -up ./testsuite/sysctl_glob_test.conf.ori ./testsuite/sysctl_glob_test.conf
|
||||
--- ./testsuite/sysctl_glob_test.conf.ori 2022-03-31 18:27:36.537486635 +0200
|
||||
+++ ./testsuite/sysctl_glob_test.conf 2022-03-31 18:27:36.537486635 +0200
|
||||
@@ -0,0 +1,6 @@
|
||||
+#
|
||||
+# Test configuration for for glob in sysctl
|
||||
+#
|
||||
+fs.protected_* = 2
|
||||
+fs.protected_hardlinks = 1
|
||||
+-fs.protected_regular
|
||||
diff -up ./testsuite/sysctl.test/sysctl_write.exp.ori ./testsuite/sysctl.test/sysctl_write.exp
|
||||
--- ./testsuite/sysctl.test/sysctl_write.exp.ori 2022-03-31 18:27:36.536486629 +0200
|
||||
+++ ./testsuite/sysctl.test/sysctl_write.exp 2022-03-31 18:27:36.536486629 +0200
|
||||
@@ -0,0 +1,29 @@
|
||||
+
|
||||
+set sysctl ${topdir}sysctl
|
||||
+
|
||||
+set test "sysctl write from command line"
|
||||
+spawn $sysctl --dry-run kernel.hostname=procps-test
|
||||
+expect_pass "$test" "/proc/sys/kernel/hostname = procps-test"
|
||||
+
|
||||
+set test "sysctl write from configuration file"
|
||||
+spawn $sysctl --dry-run -f ${topdir}testsuite/sysctl_glob_test.conf
|
||||
+expect_pass "$test" "/proc/sys/fs/protected_fifos = 2\\s+/proc/sys/fs/protected_symlinks = 2\\s+/proc/sys/fs/protected_hardlinks = 1"
|
||||
+
|
||||
+set hostname_file "/proc/sys/kernel/hostname"
|
||||
+if {[file exists ${hostname_file}]} {
|
||||
+ if {[file writable ${hostname_file}]} {
|
||||
+ unsupported "sysctl write: hostname file is writable"
|
||||
+ } else {
|
||||
+ set test "sysctl write unwritable file"
|
||||
+ spawn $sysctl -q kernel.hostname=procpstest
|
||||
+ expect_pass "$test" "sysctl: permission denied on key \"kernel.hostname\"\\s*$"
|
||||
+ expect_spawn_retval "$test" 1
|
||||
+
|
||||
+ set test "sysctl write unwritable file ignored"
|
||||
+ spawn $sysctl -q -- -kernel.hostname=procpstest
|
||||
+ expect_pass "$test" "sysctl: permission denied on key \"kernel.hostname\", ignoring\\s*$"
|
||||
+ expect_spawn_retval "$test" 0
|
||||
+ }
|
||||
+} else {
|
||||
+ unsupported "sysctl write: hostname file doe not exist"
|
||||
+}
|
@ -1,153 +0,0 @@
|
||||
diff -up ./NEWS.ori ./NEWS
|
||||
--- ./NEWS.ori 2022-08-15 11:59:35.929714848 +0200
|
||||
+++ ./NEWS 2022-08-15 12:00:12.892937479 +0200
|
||||
@@ -1,4 +1,14 @@
|
||||
procps-ng-NEXT
|
||||
+<<<<<<< HEAD
|
||||
+=======
|
||||
+ * library
|
||||
+ Re-add elogind support merge #151
|
||||
+ * ps: threads again display when -L is used with -q issue #234
|
||||
+ * ps: proper aix format string behavior was restored
|
||||
+ * sysctl: print dotted keys again
|
||||
+
|
||||
+procps-ng-4.0.0
|
||||
+>>>>>>> b159c198 (sysctl: print dotted keys again)
|
||||
---------------
|
||||
* Rename pwait to pidwait
|
||||
|
||||
diff -up ./sysctl.c.ori ./sysctl.c
|
||||
--- ./sysctl.c.ori 2022-08-15 11:59:35.934714878 +0200
|
||||
+++ ./sysctl.c 2022-08-15 12:00:12.893937485 +0200
|
||||
@@ -152,7 +152,7 @@ static SysctlSetting *setting_new(
|
||||
strcat(path + proc_len, key+1);
|
||||
else
|
||||
strcat(path + proc_len, key);
|
||||
- /* change . to / */
|
||||
+ /* change . to / for path */
|
||||
slashdot(path + proc_len, '.', '/');
|
||||
|
||||
s = xmalloc(sizeof(SysctlSetting));
|
||||
@@ -510,7 +510,8 @@ static int WriteSetting(
|
||||
|
||||
int rc = EXIT_SUCCESS;
|
||||
FILE *fp;
|
||||
- struct stat ts;
|
||||
+ struct stat ts;
|
||||
+ char *dotted_key;
|
||||
|
||||
if (!key || !path)
|
||||
return rc;
|
||||
@@ -523,13 +524,22 @@ static int WriteSetting(
|
||||
return rc;
|
||||
}
|
||||
|
||||
- if ((ts.st_mode & S_IWUSR) == 0) {
|
||||
- xwarn(_("setting key \"%s\""), key);
|
||||
+ /* Convert the globbed path into a dotted key */
|
||||
+ if ( (dotted_key = strdup(path + strlen(PROC_PATH))) == NULL) {
|
||||
+ xerrx(EXIT_FAILURE, _("strdup key"));
|
||||
+ return EXIT_FAILURE;
|
||||
+ }
|
||||
+ slashdot(dotted_key, '/', '.');
|
||||
+
|
||||
+ if ((ts.st_mode & S_IWUSR) == 0) {
|
||||
+ xwarn(_("setting key \"%s\""), dotted_key);
|
||||
+ free(dotted_key);
|
||||
return rc;
|
||||
}
|
||||
|
||||
- if (S_ISDIR(ts.st_mode)) {
|
||||
- xwarn(_("setting key \"%s\""), key);
|
||||
+ if (S_ISDIR(ts.st_mode)) {
|
||||
+ xwarn(_("setting key \"%s\""), dotted_key);
|
||||
+ free(dotted_key);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -539,7 +549,7 @@ static int WriteSetting(
|
||||
case ENOENT:
|
||||
if (!IgnoreError) {
|
||||
xwarnx(_("\"%s\" is an unknown key%s"),
|
||||
- key, (ignore_failure?_(", ignoring"):""));
|
||||
+ dotted_key, (ignore_failure?_(", ignoring"):""));
|
||||
if (!ignore_failure)
|
||||
rc = EXIT_FAILURE;
|
||||
}
|
||||
@@ -548,11 +558,11 @@ static int WriteSetting(
|
||||
case EROFS:
|
||||
case EACCES:
|
||||
xwarnx(_("permission denied on key \"%s\"%s"),
|
||||
- key, (ignore_failure?_(", ignoring"):""));
|
||||
+ dotted_key, (ignore_failure?_(", ignoring"):""));
|
||||
break;
|
||||
default:
|
||||
xwarn(_("setting key \"%s\"%s"),
|
||||
- key, (ignore_failure?_(", ignoring"):""));
|
||||
+ dotted_key, (ignore_failure?_(", ignoring"):""));
|
||||
break;
|
||||
}
|
||||
if (!ignore_failure && errno != ENOENT)
|
||||
@@ -561,7 +571,7 @@ static int WriteSetting(
|
||||
if (0 < fprintf(fp, "%s\n", value))
|
||||
rc = EXIT_SUCCESS;
|
||||
if (close_stream(fp) != 0) {
|
||||
- xwarn(_("setting key \"%s\""), path);
|
||||
+ xwarn(_("setting key \"%s\""), dotted_key);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -571,7 +581,7 @@ static int WriteSetting(
|
||||
printf("%s\n", value);
|
||||
} else {
|
||||
if (PrintName) {
|
||||
- printf("%s = %s\n", path, value);
|
||||
+ printf("%s = %s\n", dotted_key, value);
|
||||
} else {
|
||||
if (PrintNewline)
|
||||
printf("%s\n", value);
|
||||
@@ -580,6 +590,7 @@ static int WriteSetting(
|
||||
}
|
||||
}
|
||||
}
|
||||
+ free(dotted_key);
|
||||
return rc;
|
||||
}
|
||||
|
||||
diff -up ./testsuite/sysctl_slash_test.conf.ori ./testsuite/sysctl_slash_test.conf
|
||||
--- ./testsuite/sysctl_slash_test.conf.ori 2022-08-15 12:00:12.894937491 +0200
|
||||
+++ ./testsuite/sysctl_slash_test.conf 2022-08-15 12:00:12.893937485 +0200
|
||||
@@ -0,0 +1 @@
|
||||
+kernel/hostname = procps-test
|
||||
diff -up ./testsuite/sysctl.test/sysctl_write.exp.ori ./testsuite/sysctl.test/sysctl_write.exp
|
||||
--- ./testsuite/sysctl.test/sysctl_write.exp.ori 2022-08-15 11:59:35.934714878 +0200
|
||||
+++ ./testsuite/sysctl.test/sysctl_write.exp 2022-08-15 12:00:12.893937485 +0200
|
||||
@@ -3,11 +3,19 @@ set sysctl ${topdir}sysctl
|
||||
|
||||
set test "sysctl write from command line"
|
||||
spawn $sysctl --dry-run kernel.hostname=procps-test
|
||||
-expect_pass "$test" "/proc/sys/kernel/hostname = procps-test"
|
||||
+expect_pass "$test" "kernel.hostname = procps-test"
|
||||
+
|
||||
+set test "sysctl write from command line using slash"
|
||||
+spawn $sysctl --dry-run kernel/hostname=procps-test
|
||||
+expect_pass "$test" "kernel.hostname = procps-test"
|
||||
|
||||
set test "sysctl write from configuration file"
|
||||
spawn $sysctl --dry-run -f ${topdir}testsuite/sysctl_glob_test.conf
|
||||
-expect_pass "$test" "/proc/sys/fs/protected_fifos = 2\\s+/proc/sys/fs/protected_symlinks = 2\\s+/proc/sys/fs/protected_hardlinks = 1"
|
||||
+expect_pass "$test" "fs.protected_fifos = 2\\s+fs.protected_symlinks = 2\\s+fs.protected_hardlinks = 1"
|
||||
+
|
||||
+set test "sysctl write from file with slashes"
|
||||
+spawn $sysctl --dry-run -f ${topdir}testsuite/sysctl_slash_test.conf
|
||||
+expect_pass "$test" "kernel.hostname = procps-test"
|
||||
|
||||
set hostname_file "/proc/sys/kernel/hostname"
|
||||
if {[file exists ${hostname_file}]} {
|
||||
@@ -25,5 +33,5 @@ if {[file exists ${hostname_file}]} {
|
||||
expect_spawn_retval "$test" 0
|
||||
}
|
||||
} else {
|
||||
- unsupported "sysctl write: hostname file doe not exist"
|
||||
+ unsupported "sysctl write: hostname file does not exist"
|
||||
}
|
Loading…
Reference in New Issue
Block a user