calls to chdirec didn't pass 'p'.
[unix-history] / usr / src / sys / kern / kern_resource.c
CommitLineData
f406ae69
KB
1/*-
2 * Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
da7c5cc6 6 *
75e66255 7 * @(#)kern_resource.c 7.14 (Berkeley) %G%
da7c5cc6 8 */
1b64633a 9
94368568 10#include "param.h"
0cee12d3
MK
11#include "resourcevar.h"
12#include "malloc.h"
94368568 13#include "proc.h"
db1874da 14
4be63405
MH
15#include "vm/vm.h"
16
93cc02ac
BJ
17/*
18 * Resource controls and accounting.
19 */
20
8eea23a6
KM
21getpriority(curp, uap, retval)
22 struct proc *curp;
23 register struct args {
db1874da
BJ
24 int which;
25 int who;
8eea23a6
KM
26 } *uap;
27 int *retval;
28{
db1874da 29 register struct proc *p;
8fe87cbb 30 register int low = PRIO_MAX + 1;
db1874da 31
db1874da
BJ
32 switch (uap->which) {
33
34 case PRIO_PROCESS:
35 if (uap->who == 0)
8eea23a6 36 p = curp;
db1874da
BJ
37 else
38 p = pfind(uap->who);
39 if (p == 0)
957edfef 40 break;
3fa5efae 41 low = p->p_nice;
db1874da
BJ
42 break;
43
8fe87cbb
MT
44 case PRIO_PGRP: {
45 register struct pgrp *pg;
46
db1874da 47 if (uap->who == 0)
8eea23a6 48 pg = curp->p_pgrp;
8fe87cbb
MT
49 else if ((pg = pgfind(uap->who)) == NULL)
50 break;
51 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
52 if (p->p_nice < low)
3fa5efae 53 low = p->p_nice;
93cc02ac
BJ
54 }
55 break;
8fe87cbb 56 }
93cc02ac
BJ
57
58 case PRIO_USER:
59 if (uap->who == 0)
0cee12d3 60 uap->who = curp->p_ucred->cr_uid;
1d348849 61 for (p = allproc; p != NULL; p = p->p_nxt) {
0cee12d3 62 if (p->p_ucred->cr_uid == uap->who &&
3fa5efae
MK
63 p->p_nice < low)
64 low = p->p_nice;
93cc02ac 65 }
db1874da
BJ
66 break;
67
68 default:
d9c2f47f 69 return (EINVAL);
db1874da 70 }
8eea23a6 71 if (low == PRIO_MAX + 1)
d9c2f47f 72 return (ESRCH);
8eea23a6 73 *retval = low;
d9c2f47f 74 return (0);
db1874da
BJ
75}
76
8eea23a6
KM
77/* ARGSUSED */
78setpriority(curp, uap, retval)
79 struct proc *curp;
80 register struct args {
db1874da
BJ
81 int which;
82 int who;
83 int prio;
8eea23a6
KM
84 } *uap;
85 int *retval;
86{
db1874da 87 register struct proc *p;
8eea23a6 88 int found = 0, error = 0;
db1874da 89
db1874da
BJ
90 switch (uap->which) {
91
92 case PRIO_PROCESS:
93cc02ac 93 if (uap->who == 0)
8eea23a6 94 p = curp;
93cc02ac
BJ
95 else
96 p = pfind(uap->who);
db1874da 97 if (p == 0)
957edfef 98 break;
8eea23a6 99 error = donice(curp, p, uap->prio);
3fa5efae 100 found++;
db1874da
BJ
101 break;
102
8fe87cbb
MT
103 case PRIO_PGRP: {
104 register struct pgrp *pg;
105
93cc02ac 106 if (uap->who == 0)
8eea23a6 107 pg = curp->p_pgrp;
8fe87cbb
MT
108 else if ((pg = pgfind(uap->who)) == NULL)
109 break;
110 for (p = pg->pg_mem; p != NULL; p = p->p_pgrpnxt) {
8eea23a6 111 error = donice(curp, p, uap->prio);
8fe87cbb
MT
112 found++;
113 }
db1874da 114 break;
8fe87cbb 115 }
db1874da 116
93cc02ac
BJ
117 case PRIO_USER:
118 if (uap->who == 0)
0cee12d3 119 uap->who = curp->p_ucred->cr_uid;
1d348849 120 for (p = allproc; p != NULL; p = p->p_nxt)
0cee12d3 121 if (p->p_ucred->cr_uid == uap->who) {
8eea23a6 122 error = donice(curp, p, uap->prio);
3fa5efae
MK
123 found++;
124 }
93cc02ac
BJ
125 break;
126
db1874da 127 default:
d9c2f47f 128 return (EINVAL);
db1874da 129 }
3fa5efae 130 if (found == 0)
d9c2f47f
MK
131 return (ESRCH);
132 return (0);
db1874da
BJ
133}
134
8eea23a6
KM
135donice(curp, chgp, n)
136 register struct proc *curp, *chgp;
db1874da
BJ
137 register int n;
138{
0cee12d3 139 register struct pcred *pcred = curp->p_cred;
db1874da 140
0cee12d3
MK
141 if (pcred->pc_ucred->cr_uid && pcred->p_ruid &&
142 pcred->pc_ucred->cr_uid != chgp->p_ucred->cr_uid &&
143 pcred->p_ruid != chgp->p_ucred->cr_uid)
8eea23a6 144 return (EPERM);
3fa5efae
MK
145 if (n > PRIO_MAX)
146 n = PRIO_MAX;
147 if (n < PRIO_MIN)
148 n = PRIO_MIN;
0cee12d3 149 if (n < chgp->p_nice && suser(pcred->pc_ucred, &curp->p_acflag))
8eea23a6
KM
150 return (EACCES);
151 chgp->p_nice = n;
152 (void) setpri(chgp);
153 return (0);
db1874da
BJ
154}
155
8eea23a6
KM
156/* ARGSUSED */
157setrlimit(p, uap, retval)
158 struct proc *p;
159 register struct args {
db1874da
BJ
160 u_int which;
161 struct rlimit *lim;
8eea23a6
KM
162 } *uap;
163 int *retval;
164{
db1874da
BJ
165 struct rlimit alim;
166 register struct rlimit *alimp;
63ce5236 167 extern unsigned maxdmap;
8eea23a6 168 int error;
db1874da 169
8eea23a6 170 if (uap->which >= RLIM_NLIMITS)
d9c2f47f 171 return (EINVAL);
0cee12d3 172 alimp = &p->p_rlimit[uap->which];
8eea23a6
KM
173 if (error =
174 copyin((caddr_t)uap->lim, (caddr_t)&alim, sizeof (struct rlimit)))
d9c2f47f 175 return (error);
db1874da 176 if (alim.rlim_cur > alimp->rlim_max || alim.rlim_max > alimp->rlim_max)
0cee12d3 177 if (error = suser(p->p_ucred, &p->p_acflag))
d9c2f47f 178 return (error);
0cee12d3
MK
179 if (p->p_limit->p_refcnt > 1 &&
180 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) {
181 p->p_limit->p_refcnt--;
182 p->p_limit = limcopy(p->p_limit);
75e66255 183 alimp = &p->p_rlimit[uap->which];
0cee12d3
MK
184 }
185
db1874da
BJ
186 switch (uap->which) {
187
188 case RLIMIT_DATA:
d9937da6
KM
189 if (alim.rlim_cur > maxdmap)
190 alim.rlim_cur = maxdmap;
191 if (alim.rlim_max > maxdmap)
192 alim.rlim_max = maxdmap;
db1874da
BJ
193 break;
194
195 case RLIMIT_STACK:
d9937da6
KM
196 if (alim.rlim_cur > maxdmap)
197 alim.rlim_cur = maxdmap;
198 if (alim.rlim_max > maxdmap)
199 alim.rlim_max = maxdmap;
4be63405
MH
200 /*
201 * Stack is allocated to the max at exec time with only
202 * "rlim_cur" bytes accessible. If stack limit is going
203 * up make more accessible, if going down make inaccessible.
204 */
205 if (alim.rlim_cur != alimp->rlim_cur) {
206 vm_offset_t addr;
207 vm_size_t size;
208 vm_prot_t prot;
209
210 if (alim.rlim_cur > alimp->rlim_cur) {
211 prot = VM_PROT_ALL;
212 size = alim.rlim_cur - alimp->rlim_cur;
213 addr = USRSTACK - alim.rlim_cur;
214 } else {
215 prot = VM_PROT_NONE;
216 size = alimp->rlim_cur - alim.rlim_cur;
217 addr = USRSTACK - alimp->rlim_cur;
218 }
219 addr = trunc_page(addr);
220 size = round_page(size);
221 (void) vm_map_protect(&p->p_vmspace->vm_map,
222 addr, addr+size, prot, FALSE);
223 }
db1874da
BJ
224 break;
225 }
75e66255 226 *alimp = alim;
d9c2f47f 227 return (0);
db1874da
BJ
228}
229
8eea23a6
KM
230/* ARGSUSED */
231getrlimit(p, uap, retval)
232 struct proc *p;
233 register struct args {
db1874da
BJ
234 u_int which;
235 struct rlimit *rlp;
8eea23a6
KM
236 } *uap;
237 int *retval;
238{
db1874da 239
8eea23a6 240 if (uap->which >= RLIM_NLIMITS)
d9c2f47f 241 return (EINVAL);
0cee12d3 242 return (copyout((caddr_t)&p->p_rlimit[uap->which], (caddr_t)uap->rlp,
8eea23a6 243 sizeof (struct rlimit)));
db1874da
BJ
244}
245
8eea23a6
KM
246/* ARGSUSED */
247getrusage(p, uap, retval)
248 register struct proc *p;
249 register struct args {
db1874da
BJ
250 int who;
251 struct rusage *rusage;
8eea23a6
KM
252 } *uap;
253 int *retval;
254{
db1874da
BJ
255 register struct rusage *rup;
256
257 switch (uap->who) {
258
e9e38d76
MK
259 case RUSAGE_SELF: {
260 int s;
261
0cee12d3 262 rup = &p->p_stats->p_ru;
e9e38d76
MK
263 s = splclock();
264 rup->ru_stime = p->p_stime;
265 rup->ru_utime = p->p_utime;
266 splx(s);
db1874da 267 break;
e9e38d76 268 }
db1874da
BJ
269
270 case RUSAGE_CHILDREN:
0cee12d3 271 rup = &p->p_stats->p_cru;
db1874da
BJ
272 break;
273
274 default:
d9c2f47f 275 return (EINVAL);
db1874da 276 }
d9c2f47f 277 return (copyout((caddr_t)rup, (caddr_t)uap->rusage,
8eea23a6 278 sizeof (struct rusage)));
db1874da
BJ
279}
280
281ruadd(ru, ru2)
282 register struct rusage *ru, *ru2;
283{
3fd23f5c 284 register long *ip, *ip2;
db1874da
BJ
285 register int i;
286
287 timevaladd(&ru->ru_utime, &ru2->ru_utime);
288 timevaladd(&ru->ru_stime, &ru2->ru_stime);
289 if (ru->ru_maxrss < ru2->ru_maxrss)
290 ru->ru_maxrss = ru2->ru_maxrss;
291 ip = &ru->ru_first; ip2 = &ru2->ru_first;
292 for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
293 *ip++ += *ip2++;
294}
0cee12d3
MK
295
296/*
297 * Make a copy of the plimit structure.
298 * We share these structures copy-on-write after fork,
299 * and copy when a limit is changed.
300 */
301struct plimit *
302limcopy(lim)
303 struct plimit *lim;
304{
305 register struct plimit *copy;
306
307 MALLOC(copy, struct plimit *, sizeof(struct plimit),
308 M_SUBPROC, M_WAITOK);
309 bcopy(lim->pl_rlimit, copy->pl_rlimit,
310 sizeof(struct rlimit) * RLIM_NLIMITS);
311 copy->p_lflags = 0;
312 copy->p_refcnt = 1;
313 return (copy);
314}