diff options
Diffstat (limited to 'usr/src/cmd/ps')
-rw-r--r-- | usr/src/cmd/ps/ps.c | 201 | ||||
-rw-r--r-- | usr/src/cmd/ps/ucbps.c | 219 |
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); } |