xref: /csrg-svn/sys/kern/kern_resource.c (revision 28149)
1 /*
2  * Copyright (c) 1982 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	6.9 (Berkeley) 05/14/86
7  */
8 
9 #include "param.h"
10 #include "systm.h"
11 #include "dir.h"
12 #include "user.h"
13 #include "inode.h"
14 #include "proc.h"
15 #include "seg.h"
16 #include "fs.h"
17 #include "uio.h"
18 #include "vm.h"
19 #include "kernel.h"
20 
21 /*
22  * Resource controls and accounting.
23  */
24 
25 getpriority()
26 {
27 	register struct a {
28 		int	which;
29 		int	who;
30 	} *uap = (struct a *)u.u_ap;
31 	register struct proc *p;
32 	int low = PRIO_MAX + 1;
33 
34 	switch (uap->which) {
35 
36 	case PRIO_PROCESS:
37 		if (uap->who == 0)
38 			p = u.u_procp;
39 		else
40 			p = pfind(uap->who);
41 		if (p == 0)
42 			break;
43 		low = p->p_nice;
44 		break;
45 
46 	case PRIO_PGRP:
47 		if (uap->who == 0)
48 			uap->who = u.u_procp->p_pgrp;
49 		for (p = allproc; p != NULL; p = p->p_nxt) {
50 			if (p->p_pgrp == uap->who &&
51 			    p->p_nice < low)
52 				low = p->p_nice;
53 		}
54 		break;
55 
56 	case PRIO_USER:
57 		if (uap->who == 0)
58 			uap->who = u.u_uid;
59 		for (p = allproc; p != NULL; p = p->p_nxt) {
60 			if (p->p_uid == uap->who &&
61 			    p->p_nice < low)
62 				low = p->p_nice;
63 		}
64 		break;
65 
66 	default:
67 		u.u_error = EINVAL;
68 		return;
69 	}
70 	if (low == PRIO_MAX + 1) {
71 		u.u_error = ESRCH;
72 		return;
73 	}
74 	u.u_r.r_val1 = low;
75 }
76 
77 setpriority()
78 {
79 	register struct a {
80 		int	which;
81 		int	who;
82 		int	prio;
83 	} *uap = (struct a *)u.u_ap;
84 	register struct proc *p;
85 	int found = 0;
86 
87 	switch (uap->which) {
88 
89 	case PRIO_PROCESS:
90 		if (uap->who == 0)
91 			p = u.u_procp;
92 		else
93 			p = pfind(uap->who);
94 		if (p == 0)
95 			break;
96 		donice(p, uap->prio);
97 		found++;
98 		break;
99 
100 	case PRIO_PGRP:
101 		if (uap->who == 0)
102 			uap->who = u.u_procp->p_pgrp;
103 		for (p = allproc; p != NULL; p = p->p_nxt)
104 			if (p->p_pgrp == uap->who) {
105 				donice(p, uap->prio);
106 				found++;
107 			}
108 		break;
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()) {
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 (!suser())
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 
216 	switch (uap->who) {
217 
218 	case RUSAGE_SELF:
219 		rup = &u.u_ru;
220 		break;
221 
222 	case RUSAGE_CHILDREN:
223 		rup = &u.u_cru;
224 		break;
225 
226 	default:
227 		u.u_error = EINVAL;
228 		return;
229 	}
230 	u.u_error = copyout((caddr_t)rup, (caddr_t)uap->rusage,
231 	    sizeof (struct rusage));
232 }
233 
234 ruadd(ru, ru2)
235 	register struct rusage *ru, *ru2;
236 {
237 	register long *ip, *ip2;
238 	register int i;
239 
240 	timevaladd(&ru->ru_utime, &ru2->ru_utime);
241 	timevaladd(&ru->ru_stime, &ru2->ru_stime);
242 	if (ru->ru_maxrss < ru2->ru_maxrss)
243 		ru->ru_maxrss = ru2->ru_maxrss;
244 	ip = &ru->ru_first; ip2 = &ru2->ru_first;
245 	for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
246 		*ip++ += *ip2++;
247 }
248