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