From owner-svn-src-all@FreeBSD.ORG Wed Jan 25 20:14:42 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 53058106564A; Wed, 25 Jan 2012 20:14:42 +0000 (UTC) (envelope-from trociny@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 415728FC13; Wed, 25 Jan 2012 20:14:42 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q0PKEgQB043644; Wed, 25 Jan 2012 20:14:42 GMT (envelope-from trociny@svn.freebsd.org) Received: (from trociny@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q0PKEgaq043641; Wed, 25 Jan 2012 20:14:42 GMT (envelope-from trociny@svn.freebsd.org) Message-Id: <201201252014.q0PKEgaq043641@svn.freebsd.org> From: Mikolaj Golub Date: Wed, 25 Jan 2012 20:14:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r230549 - head/usr.bin/limits X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 25 Jan 2012 20:14:42 -0000 Author: trociny Date: Wed Jan 25 20:14:41 2012 New Revision: 230549 URL: http://svn.freebsd.org/changeset/base/230549 Log: Add -P option to allow get and set limits for other processes. Submitted by: Andrey Zonov MFC after: 2 weeks Modified: head/usr.bin/limits/limits.1 head/usr.bin/limits/limits.c Modified: head/usr.bin/limits/limits.1 ============================================================================== --- head/usr.bin/limits/limits.1 Wed Jan 25 20:13:37 2012 (r230548) +++ head/usr.bin/limits/limits.1 Wed Jan 25 20:14:41 2012 (r230549) @@ -19,7 +19,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 10, 2011 +.Dd January 23, 2011 .Dt LIMITS 1 .Os .Sh NAME @@ -27,7 +27,7 @@ .Nd set or display process resource limits .Sh SYNOPSIS .Nm -.Op Fl C Ar class | Fl U Ar user +.Op Fl C Ar class | Fl P Ar pid | Fl U Ar user .Op Fl SHB .Op Fl ea .Op Fl bcdflmnstuvpw Op Ar val @@ -143,6 +143,9 @@ for the class are used, if it exists, or the .Dq Li root class if the user is a superuser account. +.It Fl P Ar pid +Select or set limits for the process identified by the +.Ar pid . .It Fl S Select display or setting of .Dq soft Modified: head/usr.bin/limits/limits.c ============================================================================== --- head/usr.bin/limits/limits.c Wed Jan 25 20:13:37 2012 (r230548) +++ head/usr.bin/limits/limits.c Wed Jan 25 20:14:41 2012 (r230549) @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -249,6 +250,8 @@ static void usage(void); static int getshelltype(void); static void print_limit(rlim_t limit, unsigned divisor, const char *inf, const char *pfx, const char *sfx, const char *which); +static void getrlimit_proc(pid_t pid, int resource, struct rlimit *rlp); +static void setrlimit_proc(pid_t pid, int resource, const struct rlimit *rlp); extern char **environ; static const char rcs_string[] = RCS_STRING; @@ -262,24 +265,24 @@ main(int argc, char *argv[]) int rcswhich, shelltype; int i, num_limits = 0; int ch, doeval = 0, doall = 0; - int rtrn; + int rtrn, setproc; login_cap_t * lc = NULL; enum { ANY=0, SOFT=1, HARD=2, BOTH=3, DISPLAYONLY=4 } type = ANY; enum { RCSUNKNOWN=0, RCSSET=1, RCSSEL=2 } todo = RCSUNKNOWN; int which_limits[RLIM_NLIMITS]; rlim_t set_limits[RLIM_NLIMITS]; struct rlimit limits[RLIM_NLIMITS]; + pid_t pid; /* init resource tables */ for (i = 0; i < RLIM_NLIMITS; i++) { which_limits[i] = 0; /* Don't set/display any */ set_limits[i] = RLIM_INFINITY; - /* Get current resource values */ - getrlimit(i, &limits[i]); } + pid = -1; optarg = NULL; - while ((ch = getopt(argc, argv, ":EeC:U:BSHab:c:d:f:l:m:n:s:t:u:v:p:w:")) != -1) { + while ((ch = getopt(argc, argv, ":EeC:U:BSHP:ab:c:d:f:l:m:n:s:t:u:v:p:w:")) != -1) { switch(ch) { case 'a': doall = 1; @@ -312,6 +315,12 @@ main(int argc, char *argv[]) case 'B': type = SOFT|HARD; break; + case 'P': + if (!isdigit(*optarg) || (pid = atoi(optarg)) < 0) { + warnx("invalid pid `%s'", optarg); + usage(); + } + break; default: case ':': /* Without arg */ if ((p = strchr(rcs_string, optopt)) != NULL) { @@ -335,6 +344,30 @@ main(int argc, char *argv[]) optarg = NULL; } + if (pid != -1) { + if (cls != NULL) { + warnx("-C cannot be used with -P option"); + usage(); + } + if (pwd != NULL) { + warnx("-U cannot be used with -P option"); + usage(); + } + } + + /* Get current resource values */ + setproc = 0; + for (i = 0; i < RLIM_NLIMITS; i++) { + if (pid == -1) { + getrlimit(i, &limits[i]); + } else if (doall || num_limits == 0) { + getrlimit_proc(pid, i, &limits[i]); + } else if (which_limits[i] != 0) { + getrlimit_proc(pid, i, &limits[i]); + setproc = 1; + } + } + /* If user was specified, get class from that */ if (pwd != NULL) lc = login_getpwclass(pwd); @@ -414,6 +447,10 @@ main(int argc, char *argv[]) warnx("-e cannot be used with `cmd' option"); usage(); } + if (pid != -1) { + warnx("-P cannot be used with `cmd' option"); + usage(); + } login_close(lc); @@ -440,6 +477,14 @@ main(int argc, char *argv[]) err(1, "%s", *argv); } + if (setproc) { + for (rcswhich = 0; rcswhich < RLIM_NLIMITS; rcswhich++) { + if (which_limits[rcswhich] != 0) + setrlimit_proc(pid, rcswhich, &limits[rcswhich]); + } + exit(EXIT_SUCCESS); + } + shelltype = doeval ? getshelltype() : SH_NONE; if (type == ANY) /* Default to soft limits */ @@ -493,7 +538,8 @@ static void usage(void) { (void)fprintf(stderr, -"usage: limits [-C class|-U user] [-eaSHBE] [-bcdflmnstuvpw [val]] [[name=val ...] cmd]\n"); + "usage: limits [-C class|-P pid|-U user] [-eaSHBE] " + "[-bcdflmnstuvpw [val]] [[name=val ...] cmd]\n"); exit(EXIT_FAILURE); } @@ -677,3 +723,38 @@ getshelltype(void) return SH_SH; } +static void +getrlimit_proc(pid_t pid, int resource, struct rlimit *rlp) +{ + int error; + int name[5]; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_RLIMIT; + name[3] = pid; + name[4] = resource; + len = sizeof(*rlp); + error = sysctl(name, 5, rlp, &len, NULL, 0); + if (error == -1) + err(EXIT_FAILURE, "sysctl: kern.proc.rlimit: %d", pid); + if (len != sizeof(*rlp)) + errx(EXIT_FAILURE, "sysctl() returns wrong size"); +} + +static void +setrlimit_proc(pid_t pid, int resource, const struct rlimit *rlp) +{ + int error; + int name[5]; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_RLIMIT; + name[3] = pid; + name[4] = resource; + error = sysctl(name, 5, NULL, 0, rlp, sizeof(*rlp)); + if (error == -1) + err(EXIT_FAILURE, "sysctl: kern.proc.rlimit: %d", pid); +}