Merge remote-tracking branch 'sami/2012wk6'

This commit is contained in:
Craig Small 2012-02-12 21:56:05 +11:00
commit d9c226c695
9 changed files with 151 additions and 135 deletions

View File

@ -15,15 +15,16 @@ long strtol_or_err(const char *str, const char *errmesg)
long num; long num;
char *end = NULL; char *end = NULL;
if (str != NULL && *str != '\0') { if (str != NULL && *str != '\0') {
errno = 0; errno = 0;
num = strtol(str, &end, 10); num = strtol(str, &end, 10);
if (errno == 0 && str != end && end != NULL && *end == '\0') if (errno == 0 && str != end && end != NULL && *end == '\0')
return num; return num;
} }
error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str); error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str);
return 0; return 0;
} }
/* /*
* same as strtod(3) but exit on failure instead of returning crap * same as strtod(3) but exit on failure instead of returning crap
*/ */
@ -32,12 +33,12 @@ double strtod_or_err(const char *str, const char *errmesg)
double num; double num;
char *end = NULL; char *end = NULL;
if (str != NULL && *str != '\0') { if (str != NULL && *str != '\0') {
errno = 0; errno = 0;
num = strtod(str, &end); num = strtod(str, &end);
if (errno == 0 && str != end && end != NULL && *end == '\0') if (errno == 0 && str != end && end != NULL && *end == '\0')
return num; return num;
} }
error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str); error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str);
return 0; return 0;
} }

View File

@ -110,7 +110,7 @@ Only match processes whose real user ID is listed. Either the numerical or
symbolical value may be used. symbolical value may be used.
.TP .TP
\fB\-v\fR, \fB\-\-inverse\fR\fR \fB\-v\fR, \fB\-\-inverse\fR\fR
Negates the matching. Negates the matching. (\fBpgrep\fP only.)
.TP .TP
\fB\-x\fR, \fB\-\-exact\fR\fR \fB\-x\fR, \fB\-\-exact\fR\fR
Only match processes whose name (or command line if \-f is specified) Only match processes whose name (or command line if \-f is specified)

228
pgrep.c
View File

@ -28,8 +28,8 @@
#include <errno.h> #include <errno.h>
#include <getopt.h> #include <getopt.h>
// EXIT_SUCCESS is 0 /* EXIT_SUCCESS is 0 */
// EXIT_FAILURE is 1 /* EXIT_FAILURE is 1 */
#define EXIT_USAGE 2 #define EXIT_USAGE 2
#define EXIT_FATAL 3 #define EXIT_FATAL 3
#define XALLOC_EXIT_CODE EXIT_FATAL #define XALLOC_EXIT_CODE EXIT_FATAL
@ -87,7 +87,8 @@ static int __attribute__ ((__noreturn__)) usage(int opt)
if (i_am_pkill == 0) { if (i_am_pkill == 0) {
fputs(_(" -c, --count count of matching processes\n" fputs(_(" -c, --count count of matching processes\n"
" -d, --delimeter <string> specify output delimeter\n" " -d, --delimeter <string> specify output delimeter\n"
" -l, --list-name list PID and process name\n"), fp); " -l, --list-name list PID and process name\n"
" -v, --inverse negates the matching\n"), fp);
} }
if (i_am_pkill == 1) { if (i_am_pkill == 1) {
fputs(_(" -<sig>, --signal <sig> signal to send (either number or name)\n" fputs(_(" -<sig>, --signal <sig> signal to send (either number or name)\n"
@ -103,7 +104,6 @@ static int __attribute__ ((__noreturn__)) usage(int opt)
" -t, --terminal <tty,...> match by controlling terminal\n" " -t, --terminal <tty,...> match by controlling terminal\n"
" -u, --euid <id,...> match by effective IDs\n" " -u, --euid <id,...> match by effective IDs\n"
" -U, --uid <id,...> match by real IDs\n" " -U, --uid <id,...> match by real IDs\n"
" -v, --inverse negates the matching\n"
" -x, --exact match exectly with command name\n" " -x, --exact match exectly with command name\n"
" -F, --pidfile <file> read PIDs from file\n" " -F, --pidfile <file> read PIDs from file\n"
" -L, --logpidfile fail if PID file is not locked\n"), fp); " -L, --logpidfile fail if PID file is not locked\n"), fp);
@ -127,13 +127,13 @@ static struct el *split_list (const char *restrict str, int (*convert)(const cha
do { do {
if (i == size) { if (i == size) {
size = size * 5 / 4 + 4; size = size * 5 / 4 + 4;
// add 1 because slot zero is a count /* add 1 because slot zero is a count */
list = xrealloc (list, 1 + size * sizeof *list); list = xrealloc (list, 1 + size * sizeof *list);
} }
sep_pos = strchr (ptr, ','); sep_pos = strchr (ptr, ',');
if (sep_pos) if (sep_pos)
*sep_pos = 0; *sep_pos = 0;
// Use ++i instead of i++ because slot zero is a count /* Use ++i instead of i++ because slot zero is a count */
if (list && !convert (ptr, &list[++i])) if (list && !convert (ptr, &list[++i]))
exit (EXIT_USAGE); exit (EXIT_USAGE);
if (sep_pos) if (sep_pos)
@ -150,8 +150,8 @@ static struct el *split_list (const char *restrict str, int (*convert)(const cha
return list; return list;
} }
// strict_atol returns a Boolean: TRUE if the input string /* strict_atol returns a Boolean: TRUE if the input string
// contains a plain number, FALSE if there are any non-digits. * contains a plain number, FALSE if there are any non-digits. */
static int strict_atol (const char *restrict str, long *restrict value) static int strict_atol (const char *restrict str, long *restrict value)
{ {
int res = 0; int res = 0;
@ -176,35 +176,35 @@ static int strict_atol (const char *restrict str, long *restrict value)
#include <sys/file.h> #include <sys/file.h>
// Seen non-BSD code do this: /* Seen non-BSD code do this:
// *
//if (fcntl_lock(pid_fd, F_SETLK, F_WRLCK, SEEK_SET, 0, 0) == -1) *if (fcntl_lock(pid_fd, F_SETLK, F_WRLCK, SEEK_SET, 0, 0) == -1)
// return -1; * return -1;
*/
int fcntl_lock(int fd, int cmd, int type, int whence, int start, int len) int fcntl_lock(int fd, int cmd, int type, int whence, int start, int len)
{ {
struct flock lock[1]; struct flock lock[1];
lock->l_type = type; lock->l_type = type;
lock->l_whence = whence; lock->l_whence = whence;
lock->l_start = start; lock->l_start = start;
lock->l_len = len; lock->l_len = len;
return fcntl(fd, cmd, lock); return fcntl(fd, cmd, lock);
} }
// We try a read lock. The daemon should have a write lock. /* We try a read lock. The daemon should have a write lock.
// Seen using flock: FreeBSD code * Seen using flock: FreeBSD code */
static int has_flock(int fd) static int has_flock(int fd)
{ {
return flock(fd, LOCK_SH|LOCK_NB)==-1 && errno==EWOULDBLOCK; return flock(fd, LOCK_SH|LOCK_NB)==-1 && errno==EWOULDBLOCK;
} }
// We try a read lock. The daemon should have a write lock. /* We try a read lock. The daemon should have a write lock.
// Seen using fcntl: libslack * Seen using fcntl: libslack */
static int has_fcntl(int fd) static int has_fcntl(int fd)
{ {
struct flock f; // seriously, struct flock is for a fnctl lock! struct flock f; /* seriously, struct flock is for a fnctl lock! */
f.l_type = F_RDLCK; f.l_type = F_RDLCK;
f.l_whence = SEEK_SET; f.l_whence = SEEK_SET;
f.l_start = 0; f.l_start = 0;
@ -226,7 +226,7 @@ static struct el *read_pidfile(void)
goto just_ret; goto just_ret;
if(fstat(fd,&sbuf) || !S_ISREG(sbuf.st_mode) || sbuf.st_size<1) if(fstat(fd,&sbuf) || !S_ISREG(sbuf.st_mode) || sbuf.st_size<1)
goto out; goto out;
// type of lock, if any, is not standardized on Linux /* type of lock, if any, is not standardized on Linux */
if(opt_lock && !has_flock(fd) && !has_fcntl(fd)) if(opt_lock && !has_flock(fd) && !has_fcntl(fd))
goto out; goto out;
memset(buf,'\0',sizeof buf); memset(buf,'\0',sizeof buf);
@ -366,7 +366,7 @@ static void output_numlist (const struct el *restrict list, int num)
static void output_strlist (const struct el *restrict list, int num) static void output_strlist (const struct el *restrict list, int num)
{ {
// FIXME: escape codes /* FIXME: escape codes */
int i; int i;
const char *delim = opt_delim; const char *delim = opt_delim;
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
@ -388,7 +388,7 @@ static PROCTAB *do_openproc (void)
if (opt_oldest || opt_newest || opt_pgrp || opt_sid || opt_term) if (opt_oldest || opt_newest || opt_pgrp || opt_sid || opt_term)
flags |= PROC_FILLSTAT; flags |= PROC_FILLSTAT;
if (!(flags & PROC_FILLSTAT)) if (!(flags & PROC_FILLSTAT))
flags |= PROC_FILLSTATUS; // FIXME: need one, and PROC_FILLANY broken flags |= PROC_FILLSTATUS; /* FIXME: need one, and PROC_FILLANY broken */
if (opt_euid && !opt_negate) { if (opt_euid && !opt_negate) {
int num = opt_euid[0].num; int num = opt_euid[0].num;
int i = num; int i = num;
@ -418,7 +418,7 @@ static regex_t * do_regcomp (void)
re = xmalloc (strlen (opt_pattern) + 5); re = xmalloc (strlen (opt_pattern) + 5);
sprintf (re, "^(%s)$", opt_pattern); sprintf (re, "^(%s)$", opt_pattern);
} else { } else {
re = opt_pattern; re = opt_pattern;
} }
re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB | opt_case); re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB | opt_case);
@ -435,8 +435,8 @@ static struct el * select_procs (int *num)
{ {
PROCTAB *ptp; PROCTAB *ptp;
proc_t task; proc_t task;
unsigned long long saved_start_time; // for new/old support unsigned long long saved_start_time; /* for new/old support */
pid_t saved_pid = 0; // for new/old support pid_t saved_pid = 0; /* for new/old support */
int matches = 0; int matches = 0;
int size = 0; int size = 0;
regex_t *preg; regex_t *preg;
@ -536,7 +536,7 @@ static struct el * select_procs (int *num)
list = xrealloc(list, size * sizeof *list); list = xrealloc(list, size * sizeof *list);
} }
if (list && (opt_long || opt_echo)) { if (list && (opt_long || opt_echo)) {
char buff[5096]; // FIXME char buff[5096]; /* FIXME */
list[matches].num = task.XXXID; list[matches].num = task.XXXID;
list[matches++].str = xstrdup (cmd); list[matches++].str = xstrdup (cmd);
} else if (list) { } else if (list) {
@ -553,6 +553,24 @@ static struct el * select_procs (int *num)
return list; return list;
} }
int signal_option(int *argc, char **argv)
{
int sig;
int i = 1;
while (i < *argc) {
sig = signal_name_to_number(argv[i] + 1);
if (sig == -1 && isdigit(argv[1][1]))
sig = atoi(argv[1] + 1);
if (-1 < sig) {
memmove(argv + i, argv + i + 1,
sizeof(char *) * (*argc - i));
(*argc)--;
return sig;
}
i++;
}
return -1;
}
static void parse_opts (int argc, char **argv) static void parse_opts (int argc, char **argv)
{ {
@ -589,29 +607,19 @@ static void parse_opts (int argc, char **argv)
}; };
if (strstr (program_invocation_short_name, "pkill")) { if (strstr (program_invocation_short_name, "pkill")) {
i_am_pkill = 1; int sig;
/* Look for a signal name or number as first argument */ i_am_pkill = 1;
if (argc > 1 && argv[1][0] == '-') { sig = signal_option(&argc, argv);
int sig; if (-1 < sig)
sig = signal_name_to_number (argv[1] + 1); opt_signal = sig;
if (sig == -1 && isdigit (argv[1][1]))
sig = atoi (argv[1] + 1);
if (sig != -1) {
int i;
for (i = 2; i < argc; i++)
argv[i-1] = argv[i];
--argc;
opt_signal = sig;
}
}
/* These options are for pkill only */ /* These options are for pkill only */
strcat (opts, "e"); strcat (opts, "e");
} else { } else {
/* These options are for pgrep only */ /* These options are for pgrep only */
strcat (opts, "cld:"); strcat (opts, "cld:v");
} }
strcat (opts, "LF:fnovxP:g:s:u:U:G:t:?Vh"); strcat (opts, "LF:fnoxP:g:s:u:U:G:t:?Vh");
while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) { while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) {
switch (opt) { switch (opt) {
@ -623,41 +631,41 @@ static void parse_opts (int argc, char **argv)
case 'e': case 'e':
opt_echo = 1; opt_echo = 1;
break; break;
// case 'D': // FreeBSD: print info about non-matches for debugging /* case 'D': / * FreeBSD: print info about non-matches for debugging * /
// break; * break; */
case 'F': // FreeBSD: the arg is a file containing a PID to match case 'F': /* FreeBSD: the arg is a file containing a PID to match */
opt_pidfile = xstrdup (optarg); opt_pidfile = xstrdup (optarg);
++criteria_count; ++criteria_count;
break; break;
case 'G': // Solaris: match rgid/rgroup case 'G': /* Solaris: match rgid/rgroup */
opt_rgid = split_list (optarg, conv_gid); opt_rgid = split_list (optarg, conv_gid);
if (opt_rgid == NULL) if (opt_rgid == NULL)
usage (opt); usage (opt);
++criteria_count; ++criteria_count;
break; break;
// case 'I': // FreeBSD: require confirmation before killing /* case 'I': / * FreeBSD: require confirmation before killing * /
// break; * break;
// case 'J': // Solaris: match by project ID (name or number) /* case 'J': / * Solaris: match by project ID (name or number) * /
// break; * break; */
case 'L': // FreeBSD: fail if pidfile (see -F) not locked case 'L': /* FreeBSD: fail if pidfile (see -F) not locked */
opt_lock++; opt_lock++;
break; break;
// case 'M': // FreeBSD: specify core (OS crash dump) file /* case 'M': / * FreeBSD: specify core (OS crash dump) file * /
// break; * break; */
// case 'N': // FreeBSD: specify alternate namelist file (for us, System.map -- but we don't need it) /* case 'N': / * FreeBSD: specify alternate namelist file (for us, System.map -- but we don't need it) * /
// break; * break; */
case 'P': // Solaris: match by PPID case 'P': /* Solaris: match by PPID */
opt_ppid = split_list (optarg, conv_num); opt_ppid = split_list (optarg, conv_num);
if (opt_ppid == NULL) if (opt_ppid == NULL)
usage (opt); usage (opt);
++criteria_count; ++criteria_count;
break; break;
// case 'S': // FreeBSD: don't ignore the built-in kernel tasks /* case 'S': / * FreeBSD: don't ignore the built-in kernel tasks * /
// break; * break; */
// case 'T': // Solaris: match by "task ID" (probably not a Linux task) /* case 'T': / * Solaris: match by "task ID" (probably not a Linux task) * /
// break; * break; */
case 'U': // Solaris: match by ruid/rgroup case 'U': /* Solaris: match by ruid/rgroup */
opt_ruid = split_list (optarg, conv_uid); opt_ruid = split_list (optarg, conv_uid);
if (opt_ruid == NULL) if (opt_ruid == NULL)
usage (opt); usage (opt);
++criteria_count; ++criteria_count;
@ -665,74 +673,74 @@ static void parse_opts (int argc, char **argv)
case 'V': case 'V':
printf(PROCPS_NG_VERSION); printf(PROCPS_NG_VERSION);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
// case 'c': // Solaris: match by contract ID /* case 'c': / * Solaris: match by contract ID * /
// break; * break; */
case 'c': case 'c':
opt_count = 1; opt_count = 1;
break; break;
case 'd': // Solaris: change the delimiter case 'd': /* Solaris: change the delimiter */
opt_delim = xstrdup (optarg); opt_delim = xstrdup (optarg);
break; break;
case 'f': // Solaris: match full process name (as in "ps -f") case 'f': /* Solaris: match full process name (as in "ps -f") */
opt_full = 1; opt_full = 1;
break; break;
case 'g': // Solaris: match pgrp case 'g': /* Solaris: match pgrp */
opt_pgrp = split_list (optarg, conv_pgrp); opt_pgrp = split_list (optarg, conv_pgrp);
if (opt_pgrp == NULL) if (opt_pgrp == NULL)
usage (opt); usage (opt);
++criteria_count; ++criteria_count;
break; break;
// case 'i': // FreeBSD: ignore case. OpenBSD: withdrawn. See -I. This sucks. /* case 'i': / * FreeBSD: ignore case. OpenBSD: withdrawn. See -I. This sucks. * /
// if (opt_case) * if (opt_case)
// usage (opt); * usage (opt);
// opt_case = REG_ICASE; * opt_case = REG_ICASE;
// break; * break; */
// case 'j': // FreeBSD: restricted to the given jail ID /* case 'j': / * FreeBSD: restricted to the given jail ID * /
// break; * break; */
case 'l': // Solaris: long output format (pgrep only) Should require -f for beyond argv[0] maybe? case 'l': /* Solaris: long output format (pgrep only) Should require -f for beyond argv[0] maybe? */
opt_long = 1; opt_long = 1;
break; break;
case 'n': // Solaris: match only the newest case 'n': /* Solaris: match only the newest */
if (opt_oldest|opt_negate|opt_newest) if (opt_oldest|opt_negate|opt_newest)
usage (opt); usage (opt);
opt_newest = 1; opt_newest = 1;
++criteria_count; ++criteria_count;
break; break;
case 'o': // Solaris: match only the oldest case 'o': /* Solaris: match only the oldest */
if (opt_oldest|opt_negate|opt_newest) if (opt_oldest|opt_negate|opt_newest)
usage (opt); usage (opt);
opt_oldest = 1; opt_oldest = 1;
++criteria_count; ++criteria_count;
break; break;
case 's': // Solaris: match by session ID -- zero means self case 's': /* Solaris: match by session ID -- zero means self */
opt_sid = split_list (optarg, conv_sid); opt_sid = split_list (optarg, conv_sid);
if (opt_sid == NULL) if (opt_sid == NULL)
usage (opt); usage (opt);
++criteria_count; ++criteria_count;
break; break;
case 't': // Solaris: match by tty case 't': /* Solaris: match by tty */
opt_term = split_list (optarg, conv_str); opt_term = split_list (optarg, conv_str);
if (opt_term == NULL) if (opt_term == NULL)
usage (opt); usage (opt);
++criteria_count; ++criteria_count;
break; break;
case 'u': // Solaris: match by euid/egroup case 'u': /* Solaris: match by euid/egroup */
opt_euid = split_list (optarg, conv_uid); opt_euid = split_list (optarg, conv_uid);
if (opt_euid == NULL) if (opt_euid == NULL)
usage (opt); usage (opt);
++criteria_count; ++criteria_count;
break; break;
case 'v': // Solaris: as in grep, invert the matching (uh... applied after selection I think) case 'v': /* Solaris: as in grep, invert the matching (uh... applied after selection I think) */
if (opt_oldest|opt_negate|opt_newest) if (opt_oldest|opt_negate|opt_newest)
usage (opt); usage (opt);
opt_negate = 1; opt_negate = 1;
break; break;
// OpenBSD -x, being broken, does a plain string /* OpenBSD -x, being broken, does a plain string */
case 'x': // Solaris: use ^(regexp)$ in place of regexp (FreeBSD too) case 'x': /* Solaris: use ^(regexp)$ in place of regexp (FreeBSD too) */
opt_exact = 1; opt_exact = 1;
break; break;
// case 'z': // Solaris: match by zone ID /* case 'z': / * Solaris: match by zone ID * /
// break; * break; */
case 'h': case 'h':
usage (opt); usage (opt);
break; break;
@ -744,27 +752,27 @@ static void parse_opts (int argc, char **argv)
if(opt_lock && !opt_pidfile) if(opt_lock && !opt_pidfile)
xerrx(EXIT_FAILURE, _("-L without -F makes no sense\n" xerrx(EXIT_FAILURE, _("-L without -F makes no sense\n"
"Try `%s --help' for more information."), "Try `%s --help' for more information."),
program_invocation_short_name); program_invocation_short_name);
if(opt_pidfile){ if(opt_pidfile){
opt_pid = read_pidfile(); opt_pid = read_pidfile();
if(!opt_pid) if(!opt_pid)
xerrx(EXIT_FAILURE, _("pidfile not valid\n" xerrx(EXIT_FAILURE, _("pidfile not valid\n"
"Try `%s --help' for more information."), "Try `%s --help' for more information."),
program_invocation_short_name); program_invocation_short_name);
} }
if (argc - optind == 1) if (argc - optind == 1)
opt_pattern = argv[optind]; opt_pattern = argv[optind];
else if (argc - optind > 1) else if (argc - optind > 1)
xerrx(EXIT_FAILURE, _("only one pattern can be provided\n" xerrx(EXIT_FAILURE, _("only one pattern can be provided\n"
"Try `%s --help' for more information."), "Try `%s --help' for more information."),
program_invocation_short_name); program_invocation_short_name);
else if (criteria_count == 0) else if (criteria_count == 0)
xerrx(EXIT_FAILURE, _("no matching criteria specified\n" xerrx(EXIT_FAILURE, _("no matching criteria specified\n"
"Try `%s --help' for more information."), "Try `%s --help' for more information."),
program_invocation_short_name); program_invocation_short_name);
} }
@ -790,8 +798,8 @@ int main (int argc, char **argv)
continue; continue;
} }
if (errno==ESRCH) if (errno==ESRCH)
// gone now, which is OK /* gone now, which is OK */
continue; continue;
xwarn(_("killing pid %d failed"), procs[i].num); xwarn(_("killing pid %d failed"), procs[i].num);
} }
} else { } else {
@ -804,5 +812,5 @@ int main (int argc, char **argv)
output_numlist (procs,num); output_numlist (procs,num);
} }
} }
return !num; // exit(EXIT_SUCCESS) if match, otherwise exit(EXIT_FAILURE) return !num; /* exit(EXIT_SUCCESS) if match, otherwise exit(EXIT_FAILURE) */
} }

View File

@ -282,9 +282,6 @@ unsigned dev_to_tty(char *restrict ret, unsigned chop, dev_t dev_t_dev, int pid,
unsigned i = 0; unsigned i = 0;
int c; int c;
if(dev == 0u) goto no_tty; if(dev == 0u) goto no_tty;
if(linux_version_code > LINUX_VERSION(2, 7, 0)){ // not likely to make 2.6.xx
if(link_name(tmp, MAJOR_OF(dev), MINOR_OF(dev), pid, "tty" )) goto abbrev;
}
if(driver_name(tmp, MAJOR_OF(dev), MINOR_OF(dev) )) goto abbrev; if(driver_name(tmp, MAJOR_OF(dev), MINOR_OF(dev) )) goto abbrev;
if( link_name(tmp, MAJOR_OF(dev), MINOR_OF(dev), pid, "fd/2" )) goto abbrev; if( link_name(tmp, MAJOR_OF(dev), MINOR_OF(dev), pid, "fd/2" )) goto abbrev;
if( guess_name(tmp, MAJOR_OF(dev), MINOR_OF(dev) )) goto abbrev; if( guess_name(tmp, MAJOR_OF(dev), MINOR_OF(dev) )) goto abbrev;

13
skill.c
View File

@ -594,9 +594,16 @@ static void skillsnice_parse(int argc,
argv += optind; argv += optind;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
ENLIST(pid, strtol_or_err(argv[0], long num;
_("failed to parse argument"))); char *end = NULL;
pid_count++; errno = 0;
num = strtol(argv[0], &end, 10);
if (errno == 0 && argv[0] != end && end != NULL && *end == '\0') {
ENLIST(pid, num);
pid_count++;
} else {
ENLIST(cmd, argv[0]);
}
argv++; argv++;
} }

View File

@ -8,7 +8,7 @@ expect_pass "$test" "^\\s*Usage:\\s+\(lt-\)\?pwdx \\\[options\\\] pid\.\.\."
# Run pwdx with pid 0 which is invalid # Run pwdx with pid 0 which is invalid
set test "pwdx pid 0 should be invalid" set test "pwdx pid 0 should be invalid"
spawn $pwdx 0 spawn $pwdx 0
expect_pass "$test" "^0: No such process" expect_pass "$test" "\(lt-\)\?pwdx\: invalid process id\: 0"
# Run pwdx with existing pid # Run pwdx with existing pid
set test "pwdx finds sleep in cwd" set test "pwdx finds sleep in cwd"

View File

@ -31,7 +31,7 @@ expect_pass "$test" "^disk\[ -\]+reads\[ -\]+writes\[ -\]+IO\[ -\]+\\s+total\\s+
# Need a partition # Need a partition
set diskstats [ exec cat /proc/diskstats ] set diskstats [ exec cat /proc/diskstats ]
regexp "\\s+\\d+\\s+\\d+\\s+\(\[a-z\]+\\d+\)" $diskstats -> partition regexp "\\s+\\d+\\s+\\d+\\s+\(\[a-z\]+\\d+\)\\s+\(\[0-9\]\[0-9\]+\)" $diskstats -> partition
set test "vmstat partition (using $partition)" set test "vmstat partition (using $partition)"
spawn $vmstat -p $partition spawn $vmstat -p $partition
expect_pass "$test" "^${partition}\\s+reads" expect_pass "$test" "^${partition}\\s+reads"

View File

@ -15,8 +15,10 @@ program is run every 2 seconds.
will run until interrupted. will run until interrupted.
.SH OPTIONS .SH OPTIONS
.TP .TP
\fB\-d\fR, \fB\-\-differences\fR \fB\-d\fR, \fB\-\-differences\fR [\fIpermanent\fR]
Highlight the differences between successive updates. Highlight the differences between successive updates. Option will read
optional argument that changes highlight to be permanent, allowing to see what
has changed at least once since first iteration.
.TP .TP
\fB\-n\fR, \fB\-\-interval\fR \fIseconds\fR \fB\-n\fR, \fB\-\-interval\fR \fIseconds\fR
Specify update interval. The command will not allow quicker than 0.1 second Specify update interval. The command will not allow quicker than 0.1 second

View File

@ -67,7 +67,8 @@ static void __attribute__ ((__noreturn__))
fputs(USAGE_OPTIONS, out); fputs(USAGE_OPTIONS, out);
fputs(_(" -b, --beep beep if command has a non-zero exit\n" fputs(_(" -b, --beep beep if command has a non-zero exit\n"
" -c, --color interpret ANSI color sequences\n" " -c, --color interpret ANSI color sequences\n"
" -d, --differences highlight changes between updates\n" " -d, --differences[=<permanent>]\n"
" highlight changes between updates\n"
" -e, --errexit exit if command has a non-zero exit\n" " -e, --errexit exit if command has a non-zero exit\n"
" -n, --interval <secs> seconds to wait between updates\n" " -n, --interval <secs> seconds to wait between updates\n"
" -p, --precise attempt run command in precise intervals\n" " -p, --precise attempt run command in precise intervals\n"