summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ps
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/ps')
-rw-r--r--usr/src/cmd/ps/ps.c201
-rw-r--r--usr/src/cmd/ps/ucbps.c219
2 files changed, 169 insertions, 251 deletions
diff --git a/usr/src/cmd/ps/ps.c b/usr/src/cmd/ps/ps.c
index 1a3e91689a..1387a9440a 100644
--- a/usr/src/cmd/ps/ps.c
+++ b/usr/src/cmd/ps/ps.c
@@ -27,7 +27,7 @@
*/
/*
- * Copyright (c) 2018, Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -64,6 +64,8 @@
#include <sys/pset.h>
#include <project.h>
#include <zone.h>
+#include <assert.h>
+#include <stdbool.h>
#define min(a, b) ((a) > (b) ? (b) : (a))
#define max(a, b) ((a) < (b) ? (b) : (a))
@@ -288,7 +290,7 @@ static int nzoneid = 0;
static int kbytes_per_page;
static int pidwidth;
-static char *procdir = "/proc"; /* standard /proc directory */
+static char procdir[MAXPATHLEN]; /* standard /proc directory */
static struct ughead euid_tbl; /* table to store selected euid's */
static struct ughead ruid_tbl; /* table to store selected real uid's */
@@ -337,10 +339,22 @@ static int pidcmp(const void *p1, const void *p2);
extern int ucbmain(int, char **);
static int stdmain(int, char **);
+/* also used by ucbps.c */
+void get_psargs(bool, bool, psinfo_t *, char *, size_t);
+void print_psargs(char *, int);
+
int
main(int argc, char **argv)
{
const char *me;
+ const char *zroot = zone_get_nroot();
+
+ /*
+ * If this is a branded zone, the native procfs may mounted in a
+ * non-standard location. Apply such a path prefix if it exists.
+ */
+ (void) snprintf(procdir, sizeof (procdir), "%s/proc", zroot != NULL ?
+ zroot : "");
/*
* The original two ps'es are linked in a single binary;
@@ -1362,14 +1376,12 @@ prfind(int found, psinfo_t *psinfo, char **tpp)
static void
prcom(psinfo_t *psinfo, char *ttyp)
{
- char *cp;
- long tm;
- int bytesleft;
- int wcnt, length;
- wchar_t wchar;
+ long tm;
+ int wcnt;
struct passwd *pwd;
- int zombie_lwp;
- char zonename[ZONENAME_MAX];
+ int zombie_lwp;
+ char zonename[ZONENAME_MAX];
+ char psargs[PRMAXARGVLEN] = "";
/*
* If process is zombie, call zombie print routine and return.
@@ -1558,44 +1570,22 @@ prcom(psinfo_t *psinfo, char *ttyp)
if (psinfo->pr_time.tv_nsec > 500000000)
tm++;
}
- (void) printf(" %4ld:%.2ld", tm / 60, tm % 60); /* [L]TIME */
+ (void) printf(" %4ld:%.2ld ", tm / 60, tm % 60); /* [L]TIME */
if (zombie_lwp) {
- (void) printf(" <defunct>\n");
+ (void) printf("<defunct>\n");
return;
}
if (!fflg) { /* CMD */
wcnt = namencnt(psinfo->pr_fname, 16, 8);
- (void) printf(" %.*s\n", wcnt, psinfo->pr_fname);
+ (void) printf("%.*s\n", wcnt, psinfo->pr_fname);
return;
}
-
- /*
- * PRARGSZ == length of cmd arg string.
- */
- psinfo->pr_psargs[PRARGSZ-1] = '\0';
- bytesleft = PRARGSZ;
- for (cp = psinfo->pr_psargs; *cp != '\0'; cp += length) {
- length = mbtowc(&wchar, cp, MB_LEN_MAX);
- if (length == 0)
- break;
- if (length < 0 || !iswprint(wchar)) {
- if (length < 0)
- length = 1;
- if (bytesleft <= length) {
- *cp = '\0';
- break;
- }
- /* omit the unprintable character */
- (void) memmove(cp, cp+length, bytesleft-length);
- length = 0;
- }
- bytesleft -= length;
- }
- wcnt = namencnt(psinfo->pr_psargs, PRARGSZ, lflg ? 35 : PRARGSZ);
- (void) printf(" %.*s\n", wcnt, psinfo->pr_psargs);
+ get_psargs(false, fflg, psinfo, psargs, sizeof (psargs));
+ print_psargs(psargs, 0);
+ printf("\n");
}
/*
@@ -1650,20 +1640,98 @@ print_time(time_t tim, int width)
(void) printf("%*s", width, buf);
}
+void
+get_psargs(bool comm, bool full, psinfo_t *psinfo, char *buf, size_t bufsize)
+{
+ char *path = NULL;
+ ssize_t size = 0;
+ char *cp;
+ int fd;
+
+ assert(psinfo->pr_psargs[PRARGSZ - 1] == '\0');
+
+ if (full && getenv("SHORT_PSARGS") == NULL &&
+ asprintf(&path, "%s/%d/cmdline", procdir,
+ (int)psinfo->pr_pid) != -1 && (fd = open(path, O_RDONLY)) != -1) {
+ size = read(fd, buf, bufsize);
+ (void) close(fd);
+ }
+
+ free(path);
+
+ if (size <= 0) {
+ (void) strlcpy(buf, psinfo->pr_psargs, bufsize);
+ } else {
+ ssize_t i;
+
+ buf[bufsize - 1] = '\0';
+
+ for (cp = buf; cp - buf < size; cp++) {
+ if (*cp == '\0' && (cp - buf) + 1 < size)
+ *cp = ' ';
+ }
+
+ for (i = strlen(buf) - 1; i >= 0 && isspace(buf[i]); i--) {
+ buf[i] = '\0';
+ }
+ }
+
+ if (comm && (cp = strpbrk(buf, " \t\r\v\f\n")) != NULL)
+ *cp = '\0';
+}
+
+void
+print_psargs(char *psargs, int width)
+{
+ int bytesleft;
+ int length;
+ char *cp;
+ int wcnt;
+
+ bytesleft = strlen(psargs);
+
+ for (cp = psargs; *cp != '\0'; cp += length) {
+ wchar_t wchar;
+
+ length = mbtowc(&wchar, cp, MB_LEN_MAX);
+
+ if (length == 0)
+ break;
+
+ if (length < 0 || !iswprint(wchar)) {
+ if (length < 0)
+ length = 1;
+ if (bytesleft <= length) {
+ *cp = '\0';
+ break;
+ }
+ /* omit the unprintable character */
+ (void) memmove(cp, cp + length, bytesleft - length);
+ bytesleft -= length;
+ length = 0;
+ }
+ bytesleft -= length;
+ }
+
+ wcnt = namencnt(psargs, PRMAXARGVLEN, width);
+
+ if (width != 0) {
+ (void) printf("%.*s", width, psargs);
+ } else {
+ (void) printf("%-.*s", wcnt, psargs);
+ }
+}
+
static void
print_field(psinfo_t *psinfo, struct field *f, const char *ttyp)
{
+ char psargs[PRMAXARGVLEN] = "";
int width = f->width;
struct passwd *pwd;
struct group *grp;
time_t cputime;
- int bytesleft;
int wcnt;
- wchar_t wchar;
- char *cp;
- int length;
ulong_t mask;
- char c = '\0', *csave = NULL;
int zombie_lwp;
zombie_lwp = (Lflg && psinfo->pr_lwp.pr_sname == 'Z');
@@ -1916,12 +1984,11 @@ print_field(psinfo_t *psinfo, struct field *f, const char *ttyp)
(void) printf("%s", "<defunct>");
break;
}
- csave = strpbrk(psinfo->pr_psargs, " \t\r\v\f\n");
- if (csave) {
- c = *csave;
- *csave = '\0';
- }
- /* FALLTHROUGH */
+
+ get_psargs(true, false, psinfo, psargs, sizeof (psargs));
+ print_psargs(psargs, f->next != NULL ? width : 0);
+ break;
+
case F_ARGS:
/*
* PRARGSZ == length of cmd arg string.
@@ -1930,38 +1997,11 @@ print_field(psinfo_t *psinfo, struct field *f, const char *ttyp)
(void) printf("%-*s", width, "<defunct>");
break;
}
- psinfo->pr_psargs[PRARGSZ-1] = '\0';
- bytesleft = PRARGSZ;
- for (cp = psinfo->pr_psargs; *cp != '\0'; cp += length) {
- length = mbtowc(&wchar, cp, MB_LEN_MAX);
- if (length == 0)
- break;
- if (length < 0 || !iswprint(wchar)) {
- if (length < 0)
- length = 1;
- if (bytesleft <= length) {
- *cp = '\0';
- break;
- }
- /* omit the unprintable character */
- (void) memmove(cp, cp+length, bytesleft-length);
- length = 0;
- }
- bytesleft -= length;
- }
- wcnt = namencnt(psinfo->pr_psargs, PRARGSZ, width);
- /*
- * Print full width unless this is the last format.
- */
- if (f->next != NULL)
- (void) printf("%-*.*s", width, wcnt,
- psinfo->pr_psargs);
- else
- (void) printf("%-.*s", wcnt,
- psinfo->pr_psargs);
- if (f->fname == F_COMM && csave)
- *csave = c;
+
+ get_psargs(false, fflg, psinfo, psargs, sizeof (psargs));
+ print_psargs(psargs, f->next != NULL ? width : 0);
break;
+
case F_TASKID:
(void) printf("%*d", width, (int)psinfo->pr_taskid);
break;
@@ -2422,7 +2462,8 @@ namencnt(char *cmd, int csisize, int scrsize)
return (8); /* default to use for illegal chars */
if ((nscrsz = wcwidth(wchar)) <= 0)
return (8);
- if (csiwcnt + ncsisz > csisize || scrwcnt + nscrsz > scrsize)
+ if (csiwcnt + ncsisz > csisize ||
+ (scrsize != 0 && scrwcnt + nscrsz > scrsize))
break;
csiwcnt += ncsisz;
scrwcnt += nscrsz;
diff --git a/usr/src/cmd/ps/ucbps.c b/usr/src/cmd/ps/ucbps.c
index 6abeb1baea..05997029fd 100644
--- a/usr/src/cmd/ps/ucbps.c
+++ b/usr/src/cmd/ps/ucbps.c
@@ -21,7 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2012, Joyent, Inc. All rights reserved.
+ * Copyright 2019 Joyent, Inc.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -65,8 +65,10 @@
#include <wctype.h>
#include <stdarg.h>
#include <sys/proc.h>
+#include <sys/procfs.h>
#include <priv_utils.h>
#include <zone.h>
+#include <stdbool.h>
#define NTTYS 2 /* max ttys that can be specified with the -t option */
/* only one tty can be specified with SunOS ps */
@@ -101,6 +103,7 @@ static int nflg; /* Numerical output */
static int pflg; /* Specific process id passed as argument */
static int Uflg; /* Update private database, ups_data */
static int errflg;
+static int wflag;
static char *gettty();
static char argbuf[ARGSIZ];
@@ -133,8 +136,7 @@ static void getarg(void);
static void prtime(timestruc_t st);
static void przom(psinfo_t *psinfo);
static int num(char *);
-static int preadargs(int, psinfo_t *, char *);
-static int preadenvs(int, psinfo_t *, char *);
+static int preadenvs(int, psinfo_t *, char *, size_t);
static int prcom(int, psinfo_t *, char *);
static int namencnt(char *, int, int);
static int pscompare(const void *, const void *);
@@ -142,12 +144,18 @@ static char *err_string(int);
extern int scrwidth(wchar_t); /* header file? */
+/* from ps.c */
+void get_psargs(bool, bool, psinfo_t *, char *, size_t);
+void print_psargs(char *, int);
+
int
ucbmain(int argc, char **argv)
{
psinfo_t info; /* process information structure from /proc */
- char *psargs = NULL; /* pointer to buffer for -w and -ww options */
- char *svpsargs = NULL;
+ /*
+ * This can also store env vars, so we bump up the size.
+ */
+ char psargs[PRMAXARGVLEN * 2] = "";
struct psent *psent;
int entsize;
int nent;
@@ -235,11 +243,12 @@ ucbmain(int argc, char **argv)
case 'U': /* update private database ups_data */
Uflg++;
break;
- case 'w': /* increase display width */
+ case 'w':
if (twidth < 132)
twidth = 132;
- else /* second w option */
+ if (wflag)
twidth = NCARGS;
+ wflag++;
break;
case 'v': /* display virtual memory format */
vflg++;
@@ -371,15 +380,9 @@ ucbmain(int argc, char **argv)
(void) sprintf(hdr, "%*s TT S TIME COMMAND",
pidwidth + 1, "PID");
- twidth = twidth - strlen(hdr) + 6;
+ twidth = twidth - strlen(hdr) + 7;
(void) printf("%s\n", hdr);
- if (twidth > PRARGSZ && (psargs = malloc(twidth)) == NULL) {
- (void) fprintf(stderr, "ps: no memory\n");
- exit(1);
- }
- svpsargs = psargs;
-
/*
* Determine which processes to print info about by searching
* the /proc directory and looking at each process.
@@ -412,7 +415,7 @@ retry:
if ((psfd = open(psname, O_RDONLY)) == -1)
continue;
asfd = -1;
- if (psargs != NULL || eflg) {
+ if (eflg) {
/* now we need the proc_owner privilege */
(void) __priv_bracket(PRIV_ON);
@@ -472,26 +475,20 @@ retry:
if (!found && !tflg && !aflg && info.pr_euid != my_uid)
goto closeit;
- /*
- * Read the args for the -w and -ww cases
- */
- if (asfd > 0) {
- if ((psargs != NULL &&
- preadargs(asfd, &info, psargs) == -1) ||
- (eflg && preadenvs(asfd, &info, psargs) == -1)) {
- int saverr = errno;
+ get_psargs(false, wflag, &info, psargs, sizeof (psargs));
- (void) close(asfd);
- if (saverr == EAGAIN)
- goto retry;
- if (saverr != ENOENT)
- (void) fprintf(stderr,
- "ps: read() on %s: %s\n",
- asname, err_string(saverr));
- continue;
+ if (eflg && asfd > 0 &&
+ preadenvs(asfd, &info, psargs, sizeof (psargs)) == -1) {
+ int saverr = errno;
+
+ (void) close(asfd);
+ if (saverr == EAGAIN)
+ goto retry;
+ if (saverr != ENOENT) {
+ (void) fprintf(stderr, "ps: read() on %s: %s\n",
+ asname, err_string(saverr));
}
- } else {
- psargs = info.pr_psargs;
+ continue;
}
if (nent >= entsize) {
@@ -509,22 +506,17 @@ retry:
exit(1);
}
*psent[nent].psinfo = info;
- if (psargs == NULL)
- psent[nent].psargs = NULL;
- else {
- if ((psent[nent].psargs = malloc(strlen(psargs)+1))
- == NULL) {
- (void) fprintf(stderr, "ps: no memory\n");
- exit(1);
- }
- (void) strcpy(psent[nent].psargs, psargs);
+
+ if ((psent[nent].psargs = strndup(psargs, twidth)) == NULL) {
+ (void) fprintf(stderr, "ps: no memory\n");
+ exit(1);
}
+
psent[nent].found = found;
nent++;
closeit:
if (asfd > 0)
(void) close(asfd);
- psargs = svpsargs;
}
/* revert to non-privileged user */
@@ -555,100 +547,17 @@ usage(void) /* print usage message and quit */
}
/*
- * Read the process arguments from the process.
- * This allows >PRARGSZ characters of arguments to be displayed but,
- * unlike pr_psargs[], the process may have changed them.
- */
-#define NARG 100
-static int
-preadargs(int pfd, psinfo_t *psinfo, char *psargs)
-{
- off_t argvoff = (off_t)psinfo->pr_argv;
- size_t len;
- char *psa = psargs;
- int bsize = twidth;
- int narg = NARG;
- off_t argv[NARG];
- off_t argoff;
- off_t nextargoff;
- int i;
-#ifdef _LP64
- caddr32_t argv32[NARG];
- int is32 = (psinfo->pr_dmodel != PR_MODEL_LP64);
-#endif
-
- if (psinfo->pr_nlwp == 0 ||
- strcmp(psinfo->pr_lwp.pr_clname, "SYS") == 0)
- goto out;
-
- (void) memset(psa, 0, bsize--);
- nextargoff = 0;
- errno = EIO;
- while (bsize > 0) {
- if (narg == NARG) {
- (void) memset(argv, 0, sizeof (argv));
-#ifdef _LP64
- if (is32) {
- if ((i = pread(pfd, argv32, sizeof (argv32),
- argvoff)) <= 0) {
- if (i == 0 || errno == EIO)
- break;
- return (-1);
- }
- for (i = 0; i < NARG; i++)
- argv[i] = argv32[i];
- } else
-#endif
- if ((i = pread(pfd, argv, sizeof (argv),
- argvoff)) <= 0) {
- if (i == 0 || errno == EIO)
- break;
- return (-1);
- }
- narg = 0;
- }
- if ((argoff = argv[narg++]) == 0)
- break;
- if (argoff != nextargoff &&
- (i = pread(pfd, psa, bsize, argoff)) <= 0) {
- if (i == 0 || errno == EIO)
- break;
- return (-1);
- }
- len = strlen(psa);
- psa += len;
- *psa++ = ' ';
- bsize -= len + 1;
- nextargoff = argoff + len + 1;
-#ifdef _LP64
- argvoff += is32? sizeof (caddr32_t) : sizeof (caddr_t);
-#else
- argvoff += sizeof (caddr_t);
-#endif
- }
- while (psa > psargs && isspace(*(psa-1)))
- psa--;
-
-out:
- *psa = '\0';
- if (strlen(psinfo->pr_psargs) > strlen(psargs))
- (void) strcpy(psargs, psinfo->pr_psargs);
-
- return (0);
-}
-
-/*
* Read environment variables from the process.
* Append them to psargs if there is room.
*/
+#define NARG 100
static int
-preadenvs(int pfd, psinfo_t *psinfo, char *psargs)
+preadenvs(int pfd, psinfo_t *psinfo, char *psargs, size_t bufsize)
{
off_t envpoff = (off_t)psinfo->pr_envp;
int len;
char *psa;
- char *psainit;
- int bsize;
+ int remaining;
int nenv = NARG;
off_t envp[NARG];
off_t envoff;
@@ -659,18 +568,18 @@ preadenvs(int pfd, psinfo_t *psinfo, char *psargs)
int is32 = (psinfo->pr_dmodel != PR_MODEL_LP64);
#endif
- psainit = psa = (psargs != NULL)? psargs : psinfo->pr_psargs;
+ psa = psargs;
len = strlen(psa);
psa += len;
- bsize = twidth - len - 1;
+ remaining = bufsize - len - 1;
- if (bsize <= 0 || psinfo->pr_nlwp == 0 ||
+ if (remaining <= 0 || psinfo->pr_nlwp == 0 ||
strcmp(psinfo->pr_lwp.pr_clname, "SYS") == 0)
return (0);
nextenvoff = 0;
errno = EIO;
- while (bsize > 0) {
+ while (remaining > 0) {
if (nenv == NARG) {
(void) memset(envp, 0, sizeof (envp));
#ifdef _LP64
@@ -696,7 +605,7 @@ preadenvs(int pfd, psinfo_t *psinfo, char *psargs)
if ((envoff = envp[nenv++]) == 0)
break;
if (envoff != nextenvoff &&
- (i = pread(pfd, psa+1, bsize, envoff)) <= 0) {
+ (i = pread(pfd, psa+1, remaining, envoff)) <= 0) {
if (i == 0 || errno == EIO)
break;
return (-1);
@@ -704,7 +613,7 @@ preadenvs(int pfd, psinfo_t *psinfo, char *psargs)
*psa++ = ' ';
len = strlen(psa);
psa += len;
- bsize -= len + 1;
+ remaining -= len + 1;
nextenvoff = envoff + len + 1;
#ifdef _LP64
envpoff += is32? sizeof (caddr32_t) : sizeof (caddr_t);
@@ -712,7 +621,7 @@ preadenvs(int pfd, psinfo_t *psinfo, char *psargs)
envpoff += sizeof (caddr_t);
#endif
}
- while (psa > psainit && isspace(*(psa-1)))
+ while (psa > psargs && isspace(*(psa-1)))
psa--;
*psa = '\0';
@@ -844,12 +753,9 @@ prtpct(ushort_t pct)
static int
prcom(int found, psinfo_t *psinfo, char *psargs)
{
- char *cp;
char *tp;
- char *psa;
long tm;
- int i, wcnt, length;
- wchar_t wchar;
+ int wcnt;
struct tty *ttyp;
/*
@@ -869,7 +775,6 @@ prcom(int found, psinfo_t *psinfo, char *psargs)
* info. If 't' is set, check if term is in list of desired terminals
* and print it if it is.
*/
- i = 0;
tp = gettty(psinfo);
if (*tp == '?' && !found && !xflg)
@@ -1001,37 +906,9 @@ prcom(int found, psinfo_t *psinfo, char *psargs)
(void) printf(" %.*s", wcnt, psinfo->pr_fname);
return (1);
}
- /*
- * PRARGSZ == length of cmd arg string.
- */
- if (psargs == NULL) {
- psa = &psinfo->pr_psargs[0];
- i = PRARGSZ;
- tp = &psinfo->pr_psargs[PRARGSZ];
- } else {
- psa = psargs;
- i = strlen(psargs);
- tp = psa + i;
- }
- for (cp = psa; cp < tp; /* empty */) {
- if (*cp == 0)
- break;
- length = mbtowc(&wchar, cp, MB_LEN_MAX);
- if (length < 0 || !iswprint(wchar)) {
- (void) printf(" [ %.16s ]", psinfo->pr_fname);
- return (1);
- }
- cp += length;
- }
- wcnt = namencnt(psa, i, maxlen);
-#if 0
- /* dumps core on really long strings */
- (void) printf(" %.*s", wcnt, psa);
-#else
- (void) putchar(' ');
- (void) fwrite(psa, 1, wcnt, stdout);
-#endif
+ printf(" ");
+ print_psargs(psargs, wflag < 2 ? maxlen : 0);
return (1);
}