1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #define	_LARGEFILE64_SOURCE
27 
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <strings.h>
32 #include "libproc.h"
33 #include <sys/rctl_impl.h>
34 
35 /*
36  * getrctl() system call -- executed by subject process
37  */
38 int
pr_getrctl(struct ps_prochandle * Pr,const char * rname,rctlblk_t * old_blk,rctlblk_t * new_blk,int rflag)39 pr_getrctl(struct ps_prochandle *Pr, const char *rname,
40 	rctlblk_t *old_blk, rctlblk_t *new_blk, int rflag)
41 {
42 	sysret_t rval;
43 	argdes_t argd[6];
44 	argdes_t *adp;
45 	int error;
46 
47 	if (Pr == NULL)		/* no subject process */
48 		return (getrctl(rname, old_blk, new_blk, rflag));
49 
50 	adp = &argd[0];
51 	adp->arg_value = 0;	/* switch for getrctl in rctlsys */
52 	adp->arg_object = NULL;
53 	adp->arg_type = AT_BYVAL;
54 	adp->arg_inout = AI_INPUT;
55 	adp->arg_size = 0;
56 
57 	adp++;
58 	adp->arg_value = 0;
59 	adp->arg_object = (void *)rname;
60 	adp->arg_type = AT_BYREF;
61 	adp->arg_inout = AI_INPUT;
62 	adp->arg_size = strlen(rname) + 1;
63 
64 	adp++;
65 	if (old_blk == NULL) {
66 		adp->arg_value = 0;
67 		adp->arg_object = NULL;
68 		adp->arg_type = AT_BYVAL;
69 		adp->arg_inout = AI_INPUT;
70 		adp->arg_size = 0;
71 	} else {
72 		adp->arg_value = 0;
73 		adp->arg_object = old_blk;
74 		adp->arg_type = AT_BYREF;
75 		adp->arg_inout = AI_INPUT;
76 		adp->arg_size = rctlblk_size();
77 	}
78 
79 	adp++;
80 	if (new_blk == NULL) {
81 		adp->arg_value = 0;
82 		adp->arg_object = NULL;
83 		adp->arg_type = AT_BYVAL;
84 		adp->arg_inout = AI_OUTPUT;
85 		adp->arg_size = 0;
86 	} else {
87 		adp->arg_value = 0;
88 		adp->arg_object = new_blk;
89 		adp->arg_type = AT_BYREF;
90 		adp->arg_inout = AI_INOUT;
91 		adp->arg_size = rctlblk_size();
92 	}
93 
94 	adp++;
95 	adp->arg_value = 0;		/* obufsz isn't used by getrctl() */
96 	adp->arg_object = NULL;
97 	adp->arg_type = AT_BYVAL;
98 	adp->arg_inout = AI_INPUT;
99 	adp->arg_size = 0;
100 
101 	adp++;
102 	adp->arg_value = rflag;
103 	adp->arg_object = NULL;
104 	adp->arg_type = AT_BYVAL;
105 	adp->arg_inout = AI_INPUT;
106 	adp->arg_size = 0;
107 
108 	error = Psyscall(Pr, &rval, SYS_rctlsys, 6, &argd[0]);
109 
110 	if (error) {
111 		errno = (error > 0) ? error : ENOSYS;
112 		return (-1);
113 	}
114 	return (rval.sys_rval1);
115 }
116 
117 /*
118  * setrctl() system call -- executed by subject process
119  */
120 int
pr_setrctl(struct ps_prochandle * Pr,const char * rname,rctlblk_t * old_blk,rctlblk_t * new_blk,int rflag)121 pr_setrctl(struct ps_prochandle *Pr, const char *rname,
122 	rctlblk_t *old_blk, rctlblk_t *new_blk, int rflag)
123 {
124 	sysret_t rval;
125 	argdes_t argd[6];
126 	argdes_t *adp;
127 	int error;
128 
129 	if (Pr == NULL)		/* no subject process */
130 		return (setrctl(rname, old_blk, new_blk, rflag));
131 
132 	adp = &argd[0];
133 	adp->arg_value = 1;	/* switch for setrctl in rctlsys */
134 	adp->arg_object = NULL;
135 	adp->arg_type = AT_BYVAL;
136 	adp->arg_inout = AI_INPUT;
137 	adp->arg_size = 0;
138 
139 	adp++;
140 	adp->arg_value = 0;
141 	adp->arg_object = (void *)rname;
142 	adp->arg_type = AT_BYREF;
143 	adp->arg_inout = AI_INPUT;
144 	adp->arg_size = strlen(rname) + 1;
145 
146 	adp++;
147 	if (old_blk == NULL) {
148 		adp->arg_value = 0;
149 		adp->arg_object = NULL;
150 		adp->arg_type = AT_BYVAL;
151 		adp->arg_inout = AI_INPUT;
152 		adp->arg_size = 0;
153 	} else {
154 		adp->arg_value = 0;
155 		adp->arg_object = old_blk;
156 		adp->arg_type = AT_BYREF;
157 		adp->arg_inout = AI_INPUT;
158 		adp->arg_size = rctlblk_size();
159 	}
160 
161 	adp++;
162 	if (new_blk == NULL) {
163 		adp->arg_value = 0;
164 		adp->arg_object = NULL;
165 		adp->arg_type = AT_BYVAL;
166 		adp->arg_inout = AI_INPUT;
167 		adp->arg_size = 0;
168 	} else {
169 		adp->arg_value = 0;
170 		adp->arg_object = new_blk;
171 		adp->arg_type = AT_BYREF;
172 		adp->arg_inout = AI_INPUT;
173 		adp->arg_size = rctlblk_size();
174 	}
175 
176 	adp++;
177 	adp->arg_value = 0;		/* obufsz isn't used by setrctl() */
178 	adp->arg_object = NULL;
179 	adp->arg_type = AT_BYVAL;
180 	adp->arg_inout = AI_INPUT;
181 	adp->arg_size = 0;
182 
183 	adp++;
184 	adp->arg_value = rflag;
185 	adp->arg_object = NULL;
186 	adp->arg_type = AT_BYVAL;
187 	adp->arg_inout = AI_INPUT;
188 	adp->arg_size = 0;
189 
190 	error = Psyscall(Pr, &rval, SYS_rctlsys, 6, &argd[0]);
191 
192 	if (error) {
193 		errno = (error > 0) ? error : ENOSYS;
194 		return (-1);
195 	}
196 	return (rval.sys_rval1);
197 }
198 
199 /*
200  * setprojrctl() system call -- executed by subject process
201  */
202 int
pr_setprojrctl(struct ps_prochandle * Pr,const char * rname,rctlblk_t * new_blk,size_t size,int rflag)203 pr_setprojrctl(struct ps_prochandle *Pr, const char *rname,
204 	rctlblk_t *new_blk, size_t size, int rflag)
205 {
206 	sysret_t rval;
207 	argdes_t argd[6];
208 	argdes_t *adp;
209 	int error;
210 
211 	if (Pr == NULL)		/* no subject process */
212 		return (setprojrctl(rname, new_blk, size, rflag));
213 
214 	adp = &argd[0];
215 	adp->arg_value = 4;	/* switch for setprojrctls in rctlsys */
216 	adp->arg_object = NULL;
217 	adp->arg_type = AT_BYVAL;
218 	adp->arg_inout = AI_INPUT;
219 	adp->arg_size = 0;
220 
221 	adp++;
222 	adp->arg_value = 0;
223 	adp->arg_object = (void *)rname;
224 	adp->arg_type = AT_BYREF;
225 	adp->arg_inout = AI_INPUT;
226 	adp->arg_size = strlen(rname) + 1;
227 
228 	adp++;
229 	adp->arg_value = 0;	/* old_blk is not used by setprojrctls() */
230 	adp->arg_object = NULL;
231 	adp->arg_type = AT_BYVAL;
232 	adp->arg_inout = AI_INPUT;
233 	adp->arg_size = 0;
234 
235 
236 	adp++;
237 	if (new_blk == NULL) {
238 		adp->arg_value = 0;
239 		adp->arg_object = NULL;
240 		adp->arg_type = AT_BYVAL;
241 		adp->arg_inout = AI_INPUT;
242 		adp->arg_size = 0;
243 	} else {
244 		adp->arg_value = 0;
245 		adp->arg_object = new_blk;
246 		adp->arg_type = AT_BYREF;
247 		adp->arg_inout = AI_INPUT;
248 		adp->arg_size = rctlblk_size() * size;
249 	}
250 
251 	adp++;
252 	adp->arg_value = size;		/* obufsz is used by setrctls() */
253 	adp->arg_object = NULL;
254 	adp->arg_type = AT_BYVAL;
255 	adp->arg_inout = AI_INPUT;
256 	adp->arg_size = 0;
257 
258 	adp++;
259 	adp->arg_value = rflag;
260 	adp->arg_object = NULL;
261 	adp->arg_type = AT_BYVAL;
262 	adp->arg_inout = AI_INPUT;
263 	adp->arg_size = 0;
264 
265 	error = Psyscall(Pr, &rval, SYS_rctlsys, 6, &argd[0]);
266 
267 	if (error) {
268 		errno = (error > 0) ? error : ENOSYS;
269 		return (-1);
270 	}
271 	return (rval.sys_rval1);
272 }
273