xref: /csrg-svn/sys/kern/kern_resource.c (revision 31913)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)kern_resource.c	7.2 (Berkeley) 07/20/87
7  */
8 
9 #include "param.h"
10 #include "dir.h"
11 #include "user.h"
12 #include "proc.h"
13 
14 /*
15  * Resource controls and accounting.
16  */
17 
18 getpriority()
19 {
20 	register struct a {
21 		int	which;
22 		int	who;
23 	} *uap = (struct a *)u.u_ap;
24 	register struct proc *p;
25 	int low = PRIO_MAX + 1;
26 
27 	switch (uap->which) {
28 
29 	case PRIO_PROCESS:
30 		if (uap->who == 0)
31 			p = u.u_procp;
32 		else
33 			p = pfind(uap->who);
34 		if (p == 0)
35 			break;
36 		low = p->p_nice;
37 		break;
38 
39 	case PRIO_PGRP:
40 		if (uap->who == 0)
41 			uap->who = u.u_procp->p_pgrp;
42 		for (p = allproc; p != NULL; p = p->p_nxt) {
43 			if (p->p_pgrp == uap->who &&
44 			    p->p_nice < low)
45 				low = p->p_nice;
46 		}
47 		break;
48 
49 	case PRIO_USER:
50 		if (uap->who == 0)
51 			uap->who = u.u_uid;
52 		for (p = allproc; p != NULL; p = p->p_nxt) {
53 			if (p->p_uid == uap->who &&
54 			    p->p_nice < low)
55 				low = p->p_nice;
56 		}
57 		break;
58 
59 	default:
60 		u.u_error = EINVAL;
61 		return;
62 	}
63 	if (low == PRIO_MAX + 1) {
64 		u.u_error = ESRCH;
65 		return;
66 	}
67 	u.u_r.r_val1 = low;
68 }
69 
70 setpriority()
71 {
72 	register struct a {
73 		int	which;
74 		int	who;
75 		int	prio;
76 	} *uap = (struct a *)u.u_ap;
77 	register struct proc *p;
78 	int found = 0;
79 
80 	switch (uap->which) {
81 
82 	case PRIO_PROCESS:
83 		if (uap->who == 0)
84 			p = u.u_procp;
85 		else
86 			p = pfind(uap->who);
87 		if (p == 0)
88 			break;
89 		donice(p, uap->prio);
90 		found++;
91 		break;
92 
93 	case PRIO_PGRP:
94 		if (uap->who == 0)
95 			uap->who = u.u_procp->p_pgrp;
96 		for (p = allproc; p != NULL; p = p->p_nxt)
97 			if (p->p_pgrp == uap->who) {
98 				donice(p, uap->prio);
99 				found++;
100 			}
101 		break;
102 
103 	case PRIO_USER:
104 		if (uap->who == 0)
105 			uap->who = u.u_uid;
106 		for (p = allproc; p != NULL; p = p->p_nxt)
107 			if (p->p_uid == uap->who) {
108 				donice(p, uap->prio);
109 				found++;
110 			}
111 		break;
112 
113 	default:
114 		u.u_error = EINVAL;
115 		return;
116 	}
117 	if (found == 0)
118 		u.u_error = ESRCH;
119 }
120 
121 donice(p, n)
122 	register struct proc *p;
123 	register int n;
124 {
125 
126 	if (u.u_uid && u.u_ruid &&
127 	    u.u_uid != p->p_uid && u.u_ruid != p->p_uid) {
128 		u.u_error = EPERM;
129 		return;
130 	}
131 	if (n > PRIO_MAX)
132 		n = PRIO_MAX;
133 	if (n < PRIO_MIN)
134 		n = PRIO_MIN;
135 	if (n < p->p_nice && !suser()) {
136 		u.u_error = EACCES;
137 		return;
138 	}
139 	p->p_nice = n;
140 	(void) setpri(p);
141 }
142 
143 setrlimit()
144 {
145 	register struct a {
146 		u_int	which;
147 		struct	rlimit *lim;
148 	} *uap = (struct a *)u.u_ap;
149 	struct rlimit alim;
150 	register struct rlimit *alimp;
151 	extern unsigned maxdmap;
152 
153 	if (uap->which >= RLIM_NLIMITS) {
154 		u.u_error = EINVAL;
155 		return;
156 	}
157 	alimp = &u.u_rlimit[uap->which];
158 	u.u_error = copyin((caddr_t)uap->lim, (caddr_t)&alim,
159 		sizeof (struct rlimit));
160 	if (u.u_error)
161 		return;
162 	if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
163 		if (!suser())
164 			return;
165 	switch (uap->which) {
166 
167 	case RLIMIT_DATA:
168 		if (alim.rlim_cur > maxdmap)
169 			alim.rlim_cur = maxdmap;
170 		if (alim.rlim_max > maxdmap)
171 			alim.rlim_max = maxdmap;
172 		break;
173 
174 	case RLIMIT_STACK:
175 		if (alim.rlim_cur > maxdmap)
176 			alim.rlim_cur = maxdmap;
177 		if (alim.rlim_max > maxdmap)
178 			alim.rlim_max = maxdmap;
179 		break;
180 	}
181 	*alimp = alim;
182 	if (uap->which == RLIMIT_RSS)
183 		u.u_procp->p_maxrss = alim.rlim_cur/NBPG;
184 }
185 
186 getrlimit()
187 {
188 	register struct a {
189 		u_int	which;
190 		struct	rlimit *rlp;
191 	} *uap = (struct a *)u.u_ap;
192 
193 	if (uap->which >= RLIM_NLIMITS) {
194 		u.u_error = EINVAL;
195 		return;
196 	}
197 	u.u_error = copyout((caddr_t)&u.u_rlimit[uap->which], (caddr_t)uap->rlp,
198 	    sizeof (struct rlimit));
199 }
200 
201 getrusage()
202 {
203 	register struct a {
204 		int	who;
205 		struct	rusage *rusage;
206 	} *uap = (struct a *)u.u_ap;
207 	register struct rusage *rup;
208 
209 	switch (uap->who) {
210 
211 	case RUSAGE_SELF:
212 		rup = &u.u_ru;
213 		break;
214 
215 	case RUSAGE_CHILDREN:
216 		rup = &u.u_cru;
217 		break;
218 
219 	default:
220 		u.u_error = EINVAL;
221 		return;
222 	}
223 	u.u_error = copyout((caddr_t)rup, (caddr_t)uap->rusage,
224 	    sizeof (struct rusage));
225 }
226 
227 ruadd(ru, ru2)
228 	register struct rusage *ru, *ru2;
229 {
230 	register long *ip, *ip2;
231 	register int i;
232 
233 	timevaladd(&ru->ru_utime, &ru2->ru_utime);
234 	timevaladd(&ru->ru_stime, &ru2->ru_stime);
235 	if (ru->ru_maxrss < ru2->ru_maxrss)
236 		ru->ru_maxrss = ru2->ru_maxrss;
237 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
238 	for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
239 		*ip++ += *ip2++;
240 }
241