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