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