summaryrefslogtreecommitdiff
path: root/usr/src/cmd/plimit
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/plimit
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/plimit')
-rw-r--r--usr/src/cmd/plimit/Makefile59
-rw-r--r--usr/src/cmd/plimit/amd64/Makefile63
-rw-r--r--usr/src/cmd/plimit/i386/Makefile66
-rw-r--r--usr/src/cmd/plimit/plimit.c603
-rw-r--r--usr/src/cmd/plimit/sparcv9/Makefile67
5 files changed, 858 insertions, 0 deletions
diff --git a/usr/src/cmd/plimit/Makefile b/usr/src/cmd/plimit/Makefile
new file mode 100644
index 0000000000..bdd6fbf078
--- /dev/null
+++ b/usr/src/cmd/plimit/Makefile
@@ -0,0 +1,59 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# cmd/plimit/Makefile
+#
+
+PROG= plimit
+
+include ../Makefile.cmd
+
+$(64ONLY)SUBDIRS= $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET = all
+install := TARGET = install
+clean := TARGET = clean
+clobber := TARGET = clobber
+lint := TARGET = lint
+
+.KEEP_STATE:
+
+all: $(SUBDIRS)
+
+clean clobber lint: $(SUBDIRS)
+
+install: $(SUBDIRS)
+ -$(RM) $(ROOTPROG)
+ -$(LN) $(ISAEXEC) $(ROOTPROG)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/plimit/amd64/Makefile b/usr/src/cmd/plimit/amd64/Makefile
new file mode 100644
index 0000000000..42450afe68
--- /dev/null
+++ b/usr/src/cmd/plimit/amd64/Makefile
@@ -0,0 +1,63 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+PROG= plimit
+
+OBJS= plimit.o
+
+SRCS= $(OBJS:%.o=../%.c)
+
+include ../../Makefile.cmd
+include ../../Makefile.cmd.64
+
+CFLAGS64 += $(CCVERBOSE)
+
+LDLIBS += -lproc
+
+CPPFLAGS += -D_LARGEFILE64_SOURCE=1
+
+.KEEP_STATE:
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+install: all $(ROOTPROG64)
+
+clean:
+ $(RM) $(OBJS)
+
+lint:
+ $(LINT.c) $(SRCS) $(LDLIBS)
+
+include ../../Makefile.targ
diff --git a/usr/src/cmd/plimit/i386/Makefile b/usr/src/cmd/plimit/i386/Makefile
new file mode 100644
index 0000000000..bd858110ea
--- /dev/null
+++ b/usr/src/cmd/plimit/i386/Makefile
@@ -0,0 +1,66 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# cmd/plimit/i386/Makefile
+#
+
+PROG= plimit
+
+OBJS= plimit.o
+
+SRCS= $(OBJS:%.o=../%.c)
+
+include ../../Makefile.cmd
+
+CFLAGS += $(CCVERBOSE)
+
+LDLIBS += -lproc
+
+lint := LINTFLAGS = -x
+
+CPPFLAGS += -D_LARGEFILE64_SOURCE=1
+
+.KEEP_STATE:
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+install: all $(ROOTPROG32)
+
+clean:
+ $(RM) $(OBJS)
+
+lint:
+ $(LINT.c) $(SRCS) $(LDLIBS)
+
+include ../../Makefile.targ
diff --git a/usr/src/cmd/plimit/plimit.c b/usr/src/cmd/plimit/plimit.c
new file mode 100644
index 0000000000..b0a7fcfb03
--- /dev/null
+++ b/usr/src/cmd/plimit/plimit.c
@@ -0,0 +1,603 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.5 */
+
+#define __EXTENSIONS__ /* For strtok_r */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <signal.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/mkdev.h>
+#include <libproc.h>
+#include <priv.h>
+
+#define TRUE 1
+#define FALSE 0
+
+static int interrupt;
+static char *command;
+static int Fflag;
+static int kbytes = FALSE;
+static int mbytes = FALSE;
+static char set_current[RLIM_NLIMITS];
+static char set_maximum[RLIM_NLIMITS];
+static struct rlimit64 rlimit[RLIM_NLIMITS];
+
+static void intr(int);
+static int parse_limits(int, char *);
+static void show_limits(struct ps_prochandle *);
+static int set_limits(struct ps_prochandle *);
+
+static void
+usage()
+{
+ (void) fprintf(stderr,
+ "usage:\n"
+ " For each process, report all resource limits:\n"
+ "\t%s [-km] pid ...\n"
+ "\t-k\treport file sizes in kilobytes\n"
+ "\t-m\treport file/memory sizes in megabytes\n"
+ " For each process, set specified resource limits:\n"
+ "\t%s -{cdfnstv} soft,hard ... pid ...\n"
+ "\t-c soft,hard\tset core file size limits\n"
+ "\t-d soft,hard\tset data segment (heap) size limits\n"
+ "\t-f soft,hard\tset file size limits\n"
+ "\t-n soft,hard\tset file descriptor limits\n"
+ "\t-s soft,hard\tset stack segment size limits\n"
+ "\t-t soft,hard\tset CPU time limits\n"
+ "\t-v soft,hard\tset virtual memory size limits\n"
+ "\t(default units are as shown by the output of '%s pid')\n",
+ command, command, command);
+ exit(2);
+}
+
+int
+main(int argc, char **argv)
+{
+ int retc = 0;
+ int opt;
+ int errflg = 0;
+ int set = FALSE;
+ struct ps_prochandle *Pr;
+
+ if ((command = strrchr(argv[0], '/')) != NULL)
+ command++;
+ else
+ command = argv[0];
+
+ while ((opt = getopt(argc, argv, "Fkmc:d:f:n:s:t:v:")) != EOF) {
+ switch (opt) {
+ case 'F': /* force grabbing (no O_EXCL) */
+ Fflag = PGRAB_FORCE;
+ break;
+ case 'k':
+ kbytes = TRUE;
+ mbytes = FALSE;
+ break;
+ case 'm':
+ kbytes = FALSE;
+ mbytes = TRUE;
+ break;
+ case 'c': /* core file size */
+ set = TRUE;
+ errflg += parse_limits(RLIMIT_CORE, optarg);
+ break;
+ case 'd': /* data segment size */
+ set = TRUE;
+ errflg += parse_limits(RLIMIT_DATA, optarg);
+ break;
+ case 'f': /* file size */
+ set = TRUE;
+ errflg += parse_limits(RLIMIT_FSIZE, optarg);
+ break;
+ case 'n': /* file descriptors */
+ set = TRUE;
+ errflg += parse_limits(RLIMIT_NOFILE, optarg);
+ break;
+ case 's': /* stack segment size */
+ set = TRUE;
+ errflg += parse_limits(RLIMIT_STACK, optarg);
+ break;
+ case 't': /* CPU time */
+ set = TRUE;
+ errflg += parse_limits(RLIMIT_CPU, optarg);
+ break;
+ case 'v': /* virtual memory size */
+ set = TRUE;
+ errflg += parse_limits(RLIMIT_VMEM, optarg);
+ break;
+ default:
+ errflg = 1;
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (errflg || argc <= 0)
+ usage();
+
+ /* catch signals from terminal */
+ if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
+ (void) sigset(SIGHUP, intr);
+ if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
+ (void) sigset(SIGINT, intr);
+ if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
+ (void) sigset(SIGQUIT, intr);
+ (void) sigset(SIGPIPE, intr);
+ (void) sigset(SIGTERM, intr);
+
+ while (--argc >= 0 && !interrupt) {
+ psinfo_t psinfo;
+ char *arg;
+ pid_t pid;
+ int gret;
+
+ (void) fflush(stdout); /* process-at-a-time */
+
+ /* get the specified pid and the psinfo struct */
+ if ((pid = proc_arg_psinfo(arg = *argv++, PR_ARG_PIDS,
+ &psinfo, &gret)) == -1) {
+ (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
+ command, arg, Pgrab_error(gret));
+ retc = 1;
+ } else if ((Pr = Pgrab(pid, Fflag, &gret)) != NULL) {
+ if (Pcreate_agent(Pr) == 0) {
+ if (set) {
+ if (set_limits(Pr) != 0)
+ retc = 1;
+ } else {
+ proc_unctrl_psinfo(&psinfo);
+ (void) printf("%d:\t%.70s\n",
+ (int)pid, psinfo.pr_psargs);
+ show_limits(Pr);
+ }
+ Pdestroy_agent(Pr);
+ } else {
+ (void) fprintf(stderr,
+ "%s: cannot control process %d\n",
+ command, (int)pid);
+ retc = 1;
+ }
+ Prelease(Pr, 0);
+ } else {
+ if ((gret == G_SYS || gret == G_SELF) && !set) {
+ proc_unctrl_psinfo(&psinfo);
+ (void) printf("%d:\t%.70s\n", (int)pid,
+ psinfo.pr_psargs);
+ if (gret == G_SYS)
+ (void) printf(" [system process]\n");
+ else
+ show_limits(NULL);
+ } else {
+ (void) fprintf(stderr,
+ "%s: %s: %d\n",
+ command, Pgrab_error(gret), (int)pid);
+ retc = 1;
+ }
+ }
+ }
+
+ if (interrupt)
+ retc = 1;
+ return (retc);
+}
+
+static void
+intr(int sig)
+{
+ interrupt = sig;
+}
+
+/* ------ begin specific code ------ */
+
+/*
+ * Compute a limit, given a string:
+ * unlimited unlimited
+ * nnn k nnn kilobytes
+ * nnn m nnn megabytes (minutes for CPU time)
+ * nnn h nnn hours (for CPU time only)
+ * mm : ss minutes and seconds (for CPU time only)
+ */
+static int
+limit_value(int which, char *arg, rlim64_t *limit)
+{
+ rlim64_t value;
+ rlim64_t unit;
+ char *lastc;
+
+ if (strcmp(arg, "unlimited") == 0) {
+ *limit = RLIM64_INFINITY;
+ return (0);
+ }
+
+ if (which == RLIMIT_CPU && strchr(arg, ':') != NULL) {
+ char *minutes = strtok_r(arg, " \t:", &lastc);
+ char *seconds = strtok_r(NULL, " \t", &lastc);
+ rlim64_t sec;
+
+ if (seconds != NULL && strtok_r(NULL, " \t", &lastc) != NULL)
+ return (1);
+ value = strtoull(minutes, &lastc, 10);
+ if (*lastc != '\0' || value > RLIM64_INFINITY / 60)
+ return (1);
+ if (seconds == NULL || *seconds == '\0')
+ sec = 0;
+ else {
+ sec = strtoull(seconds, &lastc, 10);
+ if (*lastc != '\0' || sec > 60)
+ return (1);
+ }
+ value = value * 60 + sec;
+ if (value > RLIM64_INFINITY)
+ value = RLIM64_INFINITY;
+ *limit = value;
+ return (0);
+ }
+
+ switch (*(lastc = arg + strlen(arg) - 1)) {
+ case 'k':
+ unit = 1024;
+ *lastc = '\0';
+ break;
+ case 'm':
+ if (which == RLIMIT_CPU)
+ unit = 60;
+ else
+ unit = 1024 * 1024;
+ *lastc = '\0';
+ break;
+ case 'h':
+ if (which == RLIMIT_CPU)
+ unit = 60 * 60;
+ else
+ return (1);
+ *lastc = '\0';
+ break;
+ default:
+ switch (which) {
+ case RLIMIT_CPU: unit = 1; break;
+ case RLIMIT_FSIZE: unit = 512; break;
+ case RLIMIT_DATA: unit = 1024; break;
+ case RLIMIT_STACK: unit = 1024; break;
+ case RLIMIT_CORE: unit = 512; break;
+ case RLIMIT_NOFILE: unit = 1; break;
+ case RLIMIT_VMEM: unit = 1024; break;
+ }
+ break;
+ }
+
+ value = strtoull(arg, &lastc, 10);
+ if (*lastc != '\0' || value > RLIM64_INFINITY / unit)
+ return (1);
+
+ value *= unit;
+ if (value > RLIM64_INFINITY)
+ value = RLIM64_INFINITY;
+ *limit = value;
+ return (0);
+}
+
+static int
+parse_limits(int which, char *arg)
+{
+ char *lastc;
+ char *soft = strtok_r(arg, " \t,", &lastc);
+ char *hard = strtok_r(NULL, " \t", &lastc);
+ struct rlimit64 *rp = &rlimit[which];
+
+ if (hard != NULL && strtok_r(NULL, " \t", &lastc) != NULL)
+ return (1);
+
+ if (soft == NULL || *soft == '\0') {
+ rp->rlim_cur = 0;
+ set_current[which] = FALSE;
+ } else {
+ if (limit_value(which, soft, &rp->rlim_cur) != 0)
+ return (1);
+ set_current[which] = TRUE;
+ }
+
+ if (hard == NULL || *hard == '\0') {
+ rp->rlim_max = 0;
+ set_maximum[which] = FALSE;
+ } else {
+ if (limit_value(which, hard, &rp->rlim_max) != 0)
+ return (1);
+ set_maximum[which] = TRUE;
+ }
+ if (set_current[which] && set_maximum[which] &&
+ rp->rlim_cur > rp->rlim_max)
+ return (1);
+
+ return (0);
+}
+
+static void
+limit_adjust(struct rlimit64 *rp, int units)
+{
+ if (rp->rlim_cur != RLIM64_INFINITY)
+ rp->rlim_cur /= units;
+ if (rp->rlim_max != RLIM64_INFINITY)
+ rp->rlim_max /= units;
+}
+
+static char *
+limit_values(struct rlimit64 *rp)
+{
+ static char buffer[64];
+ char buf1[32];
+ char buf2[32];
+ char *s1;
+ char *s2;
+
+ if (rp->rlim_cur == RLIM64_INFINITY)
+ s1 = "unlimited";
+ else {
+ (void) sprintf(s1 = buf1, "%lld", rp->rlim_cur);
+ if (strlen(s1) < 8)
+ (void) strcat(s1, "\t");
+ }
+
+ if (rp->rlim_max == RLIM64_INFINITY)
+ s2 = "unlimited";
+ else {
+ (void) sprintf(s2 = buf2, "%lld", rp->rlim_max);
+ }
+
+ (void) sprintf(buffer, "%s\t%s", s1, s2);
+
+ return (buffer);
+}
+
+static void
+show_limits(struct ps_prochandle *Pr)
+{
+ struct rlimit64 rlim;
+ int resource;
+ char buf[32];
+ char *s;
+
+ (void) printf(" resource\t\t current\t maximum\n");
+
+ for (resource = 0; resource < RLIM_NLIMITS; resource++) {
+ if (pr_getrlimit64(Pr, resource, &rlim) != 0)
+ continue;
+
+ switch (resource) {
+ case RLIMIT_CPU:
+ s = " time(seconds)\t\t";
+ break;
+ case RLIMIT_FSIZE:
+ if (kbytes) {
+ s = " file(kbytes)\t\t";
+ limit_adjust(&rlim, 1024);
+ } else if (mbytes) {
+ s = " file(mbytes)\t\t";
+ limit_adjust(&rlim, 1024 * 1024);
+ } else {
+ s = " file(blocks)\t\t";
+ limit_adjust(&rlim, 512);
+ }
+ break;
+ case RLIMIT_DATA:
+ if (mbytes) {
+ s = " data(mbytes)\t\t";
+ limit_adjust(&rlim, 1024 * 1024);
+ } else {
+ s = " data(kbytes)\t\t";
+ limit_adjust(&rlim, 1024);
+ }
+ break;
+ case RLIMIT_STACK:
+ if (mbytes) {
+ s = " stack(mbytes)\t\t";
+ limit_adjust(&rlim, 1024 * 1024);
+ } else {
+ s = " stack(kbytes)\t\t";
+ limit_adjust(&rlim, 1024);
+ }
+ break;
+ case RLIMIT_CORE:
+ if (kbytes) {
+ s = " coredump(kbytes)\t";
+ limit_adjust(&rlim, 1024);
+ } else if (mbytes) {
+ s = " coredump(mbytes)\t";
+ limit_adjust(&rlim, 1024 * 1024);
+ } else {
+ s = " coredump(blocks)\t";
+ limit_adjust(&rlim, 512);
+ }
+ break;
+ case RLIMIT_NOFILE:
+ s = " nofiles(descriptors)\t";
+ break;
+ case RLIMIT_VMEM:
+ if (mbytes) {
+ s = " vmemory(mbytes)\t";
+ limit_adjust(&rlim, 1024 * 1024);
+ } else {
+ s = " vmemory(kbytes)\t";
+ limit_adjust(&rlim, 1024);
+ }
+ break;
+ default:
+ (void) sprintf(buf, " rlimit #%d\t", resource);
+ s = buf;
+ break;
+ }
+
+ (void) printf("%s%s\n", s, limit_values(&rlim));
+ }
+}
+
+static int
+set_one_limit(struct ps_prochandle *Pr, int which, rlim64_t cur, rlim64_t max)
+{
+ struct rlimit64 rlim;
+ int be_su = 0;
+ prpriv_t *old_prpriv = NULL, *new_prpriv = NULL;
+ priv_set_t *eset, *pset;
+ int ret = 0;
+
+ if (pr_getrlimit64(Pr, which, &rlim) != 0) {
+ (void) fprintf(stderr,
+ "%s: unable to get process limit for pid %d: %s\n",
+ command, Pstatus(Pr)->pr_pid, strerror(errno));
+ return (1);
+ }
+
+ if (!set_current[which])
+ cur = rlim.rlim_cur;
+ if (!set_maximum[which])
+ max = rlim.rlim_max;
+
+ if (max < cur)
+ max = cur;
+
+ if (max > rlim.rlim_max && Pr != NULL)
+ be_su = 1;
+ rlim.rlim_cur = cur;
+ rlim.rlim_max = max;
+
+ if (be_su) {
+ new_prpriv = proc_get_priv(Pstatus(Pr)->pr_pid);
+ if (new_prpriv == NULL) {
+ (void) fprintf(stderr,
+ "%s: unable to get process privileges for pid"
+ " %d: %s\n", command, Pstatus(Pr)->pr_pid,
+ strerror(errno));
+ return (1);
+ }
+
+ /*
+ * We only have to change the process privileges if it doesn't
+ * already have PRIV_SYS_RESOURCE. In addition, we want to make
+ * sure that we don't leave a process with elevated privileges,
+ * so we make sure the process dies if we exit unexpectedly.
+ */
+ eset = (priv_set_t *)
+ &new_prpriv->pr_sets[new_prpriv->pr_setsize *
+ priv_getsetbyname(PRIV_EFFECTIVE)];
+ pset = (priv_set_t *)
+ &new_prpriv->pr_sets[new_prpriv->pr_setsize *
+ priv_getsetbyname(PRIV_PERMITTED)];
+ if (!priv_ismember(eset, PRIV_SYS_RESOURCE)) {
+ /* Keep track of original privileges */
+ old_prpriv = proc_get_priv(Pstatus(Pr)->pr_pid);
+ if (old_prpriv == NULL) {
+ free(new_prpriv);
+ (void) fprintf(stderr,
+ "%s: unable to get process privileges "
+ "for pid %d: %s\n", command,
+ Pstatus(Pr)->pr_pid, strerror(errno));
+ return (1);
+ }
+
+ (void) priv_addset(eset, PRIV_SYS_RESOURCE);
+ (void) priv_addset(pset, PRIV_SYS_RESOURCE);
+
+ if (Psetflags(Pr, PR_KLC) != 0 ||
+ Psetpriv(Pr, new_prpriv) != 0) {
+ (void) fprintf(stderr,
+ "%s: unable to set process privileges for"
+ " pid %d: %s\n", command,
+ Pstatus(Pr)->pr_pid, strerror(errno));
+ (void) Punsetflags(Pr, PR_KLC);
+ free(new_prpriv);
+ free(old_prpriv);
+ return (1);
+ }
+ }
+ }
+
+ if (pr_setrlimit64(Pr, which, &rlim) != 0) {
+ (void) fprintf(stderr,
+ "%s: cannot set resource limit for pid %d: %s\n",
+ command, Pstatus(Pr)->pr_pid, strerror(errno));
+ ret = 1;
+ }
+
+ if (old_prpriv != NULL) {
+ if (Psetpriv(Pr, old_prpriv) != 0) {
+ /*
+ * If this fails, we can't leave a process hanging
+ * around with elevated privileges, so we'll have to
+ * release the process from libproc, knowing that it
+ * will be killed (since we set PR_KLC).
+ */
+ Pdestroy_agent(Pr);
+ (void) fprintf(stderr,
+ "%s: cannot relinquish privileges for pid %d."
+ " The process was killed.",
+ command, Pstatus(Pr)->pr_pid);
+ ret = 1;
+ }
+ if (Punsetflags(Pr, PR_KLC) != 0) {
+ (void) fprintf(stderr,
+ "%s: cannot relinquish privileges for pid %d."
+ " The process was killed.",
+ command, Pstatus(Pr)->pr_pid);
+ ret = 1;
+ }
+
+ free(old_prpriv);
+ }
+
+ if (new_prpriv != NULL)
+ free(new_prpriv);
+
+ return (ret);
+}
+
+static int
+set_limits(struct ps_prochandle *Pr)
+{
+ int which;
+ int retc = 0;
+
+ for (which = 0; which < RLIM_NLIMITS; which++) {
+ if (set_current[which] || set_maximum[which]) {
+ if (set_one_limit(Pr, which, rlimit[which].rlim_cur,
+ rlimit[which].rlim_max) != 0)
+ retc = 1;
+ }
+ }
+
+ return (retc);
+}
diff --git a/usr/src/cmd/plimit/sparcv9/Makefile b/usr/src/cmd/plimit/sparcv9/Makefile
new file mode 100644
index 0000000000..69861b1b84
--- /dev/null
+++ b/usr/src/cmd/plimit/sparcv9/Makefile
@@ -0,0 +1,67 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# cmd/plimit/sparcv9/Makefile
+#
+
+PROG= plimit
+
+OBJS= plimit.o
+
+SRCS= $(OBJS:%.o=../%.c)
+
+include ../../Makefile.cmd
+include ../../Makefile.cmd.64
+
+CFLAGS64 += $(CCVERBOSE)
+
+LDLIBS += -lproc
+
+lint := LINTFLAGS64 = -x -Xarch=v9
+
+CPPFLAGS += -D_LARGEFILE64_SOURCE=1
+
+.KEEP_STATE:
+
+%.o: ../%.c
+ $(COMPILE.c) $<
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+install: all $(ROOTPROG64)
+
+clean:
+ $(RM) $(OBJS)
+
+lint:
+ $(LINT.c) $(SRCS) $(LDLIBS)
+
+include ../../Makefile.targ